From 6a9382ea6c734896b36ce0be3d9f0bd7c9454a9d Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Tue, 1 Jul 2025 15:42:46 -0700 Subject: [PATCH 01/41] Support installing alert rules as kibana assets in packages --- .../fleet/common/services/package_to_package_policy.test.ts | 1 + .../platform/plugins/shared/fleet/common/types/models/epm.ts | 2 ++ .../applications/integrations/sections/epm/constants.tsx | 3 +++ .../plugins/shared/fleet/server/services/app_context.ts | 3 ++- .../shared/fleet/server/services/epm/kibana/assets/install.ts | 1 + 5 files changed, 9 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/fleet/common/services/package_to_package_policy.test.ts b/x-pack/platform/plugins/shared/fleet/common/services/package_to_package_policy.test.ts index c800bc4b02151..eda94deea0457 100644 --- a/x-pack/platform/plugins/shared/fleet/common/services/package_to_package_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/common/services/package_to_package_policy.test.ts @@ -35,6 +35,7 @@ describe('Fleet - packageToPackagePolicy', () => { ml_module: [], security_ai_prompt: [], security_rule: [], + alert: [], tag: [], osquery_pack_asset: [], osquery_saved_query: [], diff --git a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts index 932351b020e2f..695b898e73f16 100644 --- a/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts +++ b/x-pack/platform/plugins/shared/fleet/common/types/models/epm.ts @@ -62,6 +62,7 @@ export enum KibanaAssetType { securityAIPrompt = 'security_ai_prompt', securityRule = 'security_rule', cloudSecurityPostureRuleTemplate = 'csp_rule_template', + alert = 'alert', osqueryPackAsset = 'osquery_pack_asset', osquerySavedQuery = 'osquery_saved_query', tag = 'tag', @@ -81,6 +82,7 @@ export enum KibanaSavedObjectType { securityAIPrompt = 'security-ai-prompt', securityRule = 'security-rule', cloudSecurityPostureRuleTemplate = 'csp-rule-template', + alert = 'alert', osqueryPackAsset = 'osquery-pack-asset', osquerySavedQuery = 'osquery-saved-query', tag = 'tag', diff --git a/x-pack/platform/plugins/shared/fleet/public/applications/integrations/sections/epm/constants.tsx b/x-pack/platform/plugins/shared/fleet/public/applications/integrations/sections/epm/constants.tsx index 266aae8636710..87b8e0ff7c627 100644 --- a/x-pack/platform/plugins/shared/fleet/public/applications/integrations/sections/epm/constants.tsx +++ b/x-pack/platform/plugins/shared/fleet/public/applications/integrations/sections/epm/constants.tsx @@ -71,6 +71,9 @@ export const AssetTitleMap: Record< defaultMessage: 'Benchmark rules', } ), + alert: i18n.translate('xpack.fleet.epm.assetTitles.alert', { + defaultMessage: 'Alert rules', + }), 'ml-module': i18n.translate('xpack.fleet.epm.assetTitles.mlModules', { defaultMessage: 'Anomaly detection configurations', }), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts index 5d7418b0afaf7..52c35739d2208 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts @@ -45,6 +45,7 @@ import type { PostAgentPolicyCreateCallback, PostAgentPolicyUpdateCallback, } from '../types'; +import { KibanaSavedObjectType } from '../types'; import type { FleetAppContext } from '../plugin'; import type { TelemetryEventsSender } from '../telemetry/sender'; import { UNINSTALL_TOKENS_SAVED_OBJECT_TYPE } from '../constants'; @@ -203,7 +204,7 @@ class AppContextService { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(request, { - includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, KibanaSavedObjectType.alert], excludedExtensions: [SECURITY_EXTENSION_ID], }); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index b468d20595e00..5d7043c90844d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -75,6 +75,7 @@ export const KibanaSavedObjectTypeMapping: Record Date: Tue, 8 Jul 2025 15:10:11 -0700 Subject: [PATCH 02/41] Introduce alert rule as epm kibana asset type --- .../services/epm/kibana/assets/install.ts | 106 +++++++++++++----- .../server/services/epm/packages/install.ts | 9 -- 2 files changed, 80 insertions(+), 35 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 5d7043c90844d..f90c8579d39af 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,6 +16,8 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; +// import { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -46,10 +48,19 @@ const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => errors.map(({ type, id, error }) => ({ type, id, error })) // discard other fields ); const validKibanaAssetTypes = new Set(Object.values(KibanaAssetType)); -type SavedObjectToBe = Required> & { + +type SavedObjectKibanaAssetTypes = Exclude; +type SavedObjectToBe = Required< + Pick> +> & { type: KibanaSavedObjectType; }; -export type ArchiveAsset = Pick< + +type AlertRuleAsset = typeof alertRuleBodySchema & { + id: string; + type: KibanaSavedObjectType.alert; +}; +type SavedObjectAsset = Pick< SavedObject, | 'id' | 'attributes' @@ -61,9 +72,25 @@ export type ArchiveAsset = Pick< type: KibanaSavedObjectType; }; +export type ArchiveAsset = SavedObjectAsset | AlertRuleAsset; +interface SavedObjectAssetEntry { + path: string; + asset: SavedObjectAsset; + assetType: SavedObjectKibanaAssetTypes; +} + +interface AlertRuleAssetEntry { + path: string; + asset: AlertRuleAsset; + assetType: KibanaAssetType.alert; +} + +type ArchiveAssetEntry = SavedObjectAssetEntry | AlertRuleAssetEntry; + // KibanaSavedObjectTypes are used to ensure saved objects being created for a given // KibanaAssetType have the correct type export const KibanaSavedObjectTypeMapping: Record = { + [KibanaAssetType.alert]: KibanaSavedObjectType.alert, [KibanaAssetType.dashboard]: KibanaSavedObjectType.dashboard, [KibanaAssetType.indexPattern]: KibanaSavedObjectType.indexPattern, [KibanaAssetType.map]: KibanaSavedObjectType.map, @@ -75,17 +102,16 @@ export const KibanaSavedObjectTypeMapping: Record ArchiveAsset[]> = { +const AssetFilters: Record ArchiveAssetEntry[]> = { [KibanaAssetType.indexPattern]: removeReservedIndexPatterns, }; -export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectToBe { +export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObjectToBe { // convert that to an object const so: Partial = { type: asset.type, @@ -116,7 +142,7 @@ export async function installKibanaAssets(options: { }): Promise { const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger } = options; - let assetsToInstall: ArchiveAsset[] = []; + let assetsToInstall: ArchiveAssetEntry[] = []; let res: SavedObjectsImportSuccess[] = []; const installManagedIndexPatternOnce = once(() => @@ -126,25 +152,49 @@ export async function installKibanaAssets(options: { }) ); + interface InstallGroups { + asSavedObjects: SavedObjectAsset[]; + asAlertRules: AlertRuleAsset[]; + } + const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { + return assetsToInstall.reduce( + (installGroups, assetEntry) => { + if (assetEntry.assetType === KibanaAssetType.alert) { + installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; + return installGroups; + } + + installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; + return installGroups; + }, + { asSavedObjects: [], asAlertRules: [] } + ); + }; + async function flushAssetsToInstall() { await installManagedIndexPatternOnce(); + // split assets into SO installs and alert rule installs + const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); + + await installAlertRules({ logger, alertRuleAssets: asAlertRules }); + const installedAssets = await installKibanaSavedObjects({ logger, savedObjectsImporter, - kibanaAssets: assetsToInstall, + kibanaAssets: asSavedObjects, assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); assetsToInstall = []; res = [...res, ...installedAssets]; } - await kibanaAssetsArchiveIterator(async ({ assetType, asset }) => { - const assetFilter = AssetFilters[assetType]; + await kibanaAssetsArchiveIterator(async (entry) => { + const assetFilter = AssetFilters[entry.assetType]; if (assetFilter) { - assetsToInstall = [...assetsToInstall, ...assetFilter([asset])]; + assetsToInstall = [...assetsToInstall, ...assetFilter([entry])]; } else { - assetsToInstall.push(asset); + assetsToInstall.push(entry); } if (assetsToInstall.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { @@ -357,13 +407,7 @@ export const isKibanaAssetType = (path: string) => { }; function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallContext) { - return ( - onEntry: (entry: { - path: string; - asset: ArchiveAsset; - assetType: KibanaAssetType; - }) => Promise - ) => { + return (onEntry: (entry: ArchiveAssetEntry) => Promise) => { return packageInstallContext.archiveIterator.traverseEntries(async (entry) => { if (!entry.buffer) { return; @@ -372,11 +416,10 @@ function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallCon const asset = JSON.parse(entry.buffer.toString('utf8')); const assetType = getPathParts(entry.path).type as KibanaAssetType; - const soType = KibanaSavedObjectTypeMapping[assetType]; if (!validKibanaAssetTypes.has(assetType)) { return; } - + const soType = KibanaSavedObjectTypeMapping[assetType]; if (asset.type === soType) { await onEntry({ path: entry.path, assetType, asset }); } @@ -424,7 +467,7 @@ export async function installKibanaSavedObjects({ assetsChunkSize, logger, }: { - kibanaAssets: ArchiveAsset[]; + kibanaAssets: SavedObjectAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; assetsChunkSize?: number; @@ -480,7 +523,7 @@ async function installKibanaSavedObjectsChunk({ logger, refresh, }: { - kibanaAssets: ArchiveAsset[]; + kibanaAssets: SavedObjectAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; refresh?: boolean | 'wait_for'; @@ -576,10 +619,10 @@ async function installKibanaSavedObjectsChunk({ } // Filter out any reserved index patterns -function removeReservedIndexPatterns(kibanaAssets: ArchiveAsset[]) { +function removeReservedIndexPatterns(kibanaAssets: ArchiveAssetEntry[]) { const reservedPatterns = indexPatternTypes.map((pattern) => `${pattern}-*`); - return kibanaAssets.filter((asset) => !reservedPatterns.includes(asset.id)); + return kibanaAssets.filter((assetEntry) => !reservedPatterns.includes(assetEntry.asset.id)); } export function toAssetReference({ id, type }: SavedObject) { @@ -588,6 +631,17 @@ export function toAssetReference({ id, type }: SavedObject) { return reference; } -function hasReferences(assetsToInstall: ArchiveAsset[]) { - return assetsToInstall.some((asset) => asset.references?.length); +function hasReferences(assetsToInstall: SavedObjectAsset[]) { + return assetsToInstall.some((asset) => asset.references.length); +} + +async function installAlertRules({ + logger, + alertRuleAssets, +}: { + logger: Logger; + alertRuleAssets: AlertRuleAsset[]; +}): Promise { + logger.debug(`no-op alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); + return Promise.resolve(); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index 9df315427828f..da15fe5a86806 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -40,7 +40,6 @@ import type { InstallResult, InstallSource, InstallType, - KibanaAssetType, PackageVerificationResult, InstallResultStatus, } from '../../../types'; @@ -72,8 +71,6 @@ import { unpackBufferToAssetsMap, } from '../archive'; import { createArchiveIteratorFromMap } from '../archive/archive_iterator'; -import { toAssetReference } from '../kibana/assets/install'; -import type { ArchiveAsset } from '../kibana/assets/install'; import type { PackageUpdateEvent } from '../../upgrade_sender'; import { sendTelemetryEvents, UpdateEventType } from '../../upgrade_sender'; import { auditLoggingService } from '../../audit_logging'; @@ -1254,12 +1251,6 @@ export async function createInstallation(options: { return created; } -export const kibanaAssetsToAssetsRef = ( - kibanaAssets: Record -): KibanaAssetReference[] => { - return Object.values(kibanaAssets).flat().map(toAssetReference); -}; - export const saveKibanaAssetsRefs = async ( savedObjectsClient: SavedObjectsClientContract, pkgName: string, From 20d752489c5bb55c3a58ac71e05d3cb33d1df6c4 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Wed, 9 Jul 2025 15:27:05 -0700 Subject: [PATCH 03/41] WIP: Add alertingStart to app context, and alertingRulesClient to package install --- .../plugins/shared/fleet/server/plugin.ts | 5 +++- .../fleet/server/routes/epm/handlers.ts | 13 +++++++- .../fleet/server/services/app_context.ts | 7 +++++ .../server/services/epm/packages/install.ts | 30 +++++++++++++++++-- 4 files changed, 51 insertions(+), 4 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/plugin.ts b/x-pack/platform/plugins/shared/fleet/server/plugin.ts index 83627f6e7a3db..4825753815761 100644 --- a/x-pack/platform/plugins/shared/fleet/server/plugin.ts +++ b/x-pack/platform/plugins/shared/fleet/server/plugin.ts @@ -40,6 +40,7 @@ import type { SecurityPluginSetup, SecurityPluginStart, } from '@kbn/security-plugin/server'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import type { FieldsMetadataServerSetup } from '@kbn/fields-metadata-plugin/server'; import type { @@ -166,6 +167,7 @@ export interface FleetStartDeps { data: DataPluginStart; licensing: LicensingPluginStart; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; + alerting: AlertingServerStart; security: SecurityPluginStart; telemetry?: TelemetryPluginStart; savedObjectsTagging: SavedObjectTaggingStart; @@ -178,6 +180,7 @@ export interface FleetAppContext { data: DataPluginStart; encryptedSavedObjectsStart?: EncryptedSavedObjectsPluginStart; encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup; + alertingStart: AlertingServerStart; securityCoreStart: SecurityServiceStart; securitySetup: SecurityPluginSetup; securityStart: SecurityPluginStart; @@ -555,7 +558,6 @@ export class FleetPlugin const routeAuthz = routeRequiredAuthz ? calculateRouteAuthz(authz, routeRequiredAuthz) : undefined; - const getInternalSoClient = (): SavedObjectsClientContract => appContextService .getSavedObjects() @@ -712,6 +714,7 @@ export class FleetPlugin data: plugins.data, encryptedSavedObjectsStart: plugins.encryptedSavedObjects, encryptedSavedObjectsSetup: this.encryptedSavedObjectsSetup, + alertingStart: plugins.alerting, securityCoreStart: core.security, securitySetup: this.securitySetup, securityStart: plugins.security, diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts index 50448f9431a8f..979e694fa5657 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts @@ -303,8 +303,10 @@ export const installPackageFromRegistryHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; - const { pkgName, pkgVersion } = request.params; const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username); @@ -316,6 +318,7 @@ export const installPackageFromRegistryHandler: FleetRequestHandler< savedObjectsClient, pkgkey: pkgVersion ? `${pkgName}-${pkgVersion}` : pkgName, esClient, + alertingRulesClient, spaceId, force: request.body?.force, ignoreConstraints: request.body?.ignore_constraints, @@ -348,6 +351,9 @@ export const createCustomIntegrationHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; const kibanaVersion = appContextService.getKibanaVersion(); const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username); @@ -361,6 +367,7 @@ export const createCustomIntegrationHandler: FleetRequestHandler< pkgName: integrationName, datasets, esClient, + alertingRulesClient, spaceId, force, authorizationHeader, @@ -477,6 +484,9 @@ export const installPackageByUploadHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const contentType = request.headers['content-type'] as string; // from types it could also be string[] or undefined but this is checked later const archiveBuffer = Buffer.from(request.body); const spaceId = fleetContext.spaceId; @@ -487,6 +497,7 @@ export const installPackageByUploadHandler: FleetRequestHandler< installSource, savedObjectsClient, esClient, + alertingRulesClient, archiveBuffer, spaceId, contentType, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts index 52c35739d2208..83990d3d94fdd 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts @@ -11,6 +11,7 @@ import { kibanaPackageJson } from '@kbn/repo-info'; import type { HttpServiceSetup, KibanaRequest } from '@kbn/core-http-server'; import { kibanaRequestFactory } from '@kbn/core-http-server-utils'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server'; import type { EncryptedSavedObjectsClient, @@ -62,6 +63,7 @@ class AppContextService { private data: DataPluginStart | undefined; private esClient: ElasticsearchClient | undefined; private experimentalFeatures: ExperimentalFeatures = allowedExperimentalValues; + private alertingStart: AlertingServerStart | undefined; private securityCoreStart: SecurityServiceStart | undefined; private securitySetup: SecurityPluginSetup | undefined; private securityStart: SecurityPluginStart | undefined; @@ -91,6 +93,7 @@ class AppContextService { this.encryptedSavedObjectsStart = appContext.encryptedSavedObjectsStart; this.encryptedSavedObjects = appContext.encryptedSavedObjectsStart?.getClient(); this.encryptedSavedObjectsSetup = appContext.encryptedSavedObjectsSetup; + this.alertingStart = appContext.alertingStart; this.securityCoreStart = appContext.securityCoreStart; this.securitySetup = appContext.securitySetup; this.securityStart = appContext.securityStart; @@ -138,6 +141,10 @@ class AppContextService { return this.encryptedSavedObjects; } + public getAlerting() { + return this.alertingStart!; + } + public getSecurityCore() { return this.securityCoreStart!; } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index da15fe5a86806..f317d98a3e4e9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -21,6 +21,7 @@ import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import pRetry from 'p-retry'; import type { LicenseType } from '@kbn/licensing-plugin/server'; +import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { KibanaAssetReference, @@ -174,6 +175,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -183,6 +185,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient, pkgName, esClient, + alertingRulesClient, pkgVersion, force = false, spaceId = DEFAULT_SPACE_ID, @@ -215,6 +218,7 @@ export async function ensureInstalledPackage(options: { pkgkey, spaceId, esClient, + alertingRulesClient, neverIgnoreVerificationError: !force, force: true, // Always force outdated packages to be installed if a later version isn't installed authorizationHeader, @@ -270,6 +274,7 @@ export async function handleInstallPackageFailure({ pkgVersion, installedPkg, esClient, + alertingRulesClient, spaceId, authorizationHeader, keepFailedInstallation, @@ -280,6 +285,7 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -337,6 +343,7 @@ export async function handleInstallPackageFailure({ savedObjectsClient, pkgkey, esClient, + alertingRulesClient, spaceId, authorizationHeader, retryFromLastState: true, @@ -358,6 +365,7 @@ export async function handleInstallPackageFailure({ savedObjectsClient, pkgkey: prevVersion, esClient, + alertingRulesClient, spaceId, force: true, authorizationHeader, @@ -394,6 +402,7 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -417,6 +426,7 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -425,6 +435,7 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -460,6 +471,7 @@ async function installPackageFromRegistry({ savedObjectsClient, pkgkey, esClient, + alertingRulesClient, spaceId, authorizationHeader, force = false, @@ -565,6 +577,7 @@ async function installPackageFromRegistry({ installType, savedObjectsClient, esClient, + alertingRulesClient, spaceId, force, packageInstallContext, @@ -606,6 +619,7 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -631,6 +645,7 @@ export async function installPackageWithStateMachine(options: { savedObjectsClient, force, esClient, + alertingRulesClient, spaceId, verificationResult, authorizationHeader, @@ -781,6 +796,7 @@ export async function installPackageWithStateMachine(options: { installedPkg, spaceId, esClient, + alertingRulesClient, authorizationHeader, keepFailedInstallation, }); @@ -809,6 +825,7 @@ export async function installPackageWithStateMachine(options: { async function installPackageByUpload({ savedObjectsClient, esClient, + alertingRulesClient, archiveBuffer, contentType, spaceId, @@ -893,6 +910,7 @@ async function installPackageByUpload({ installType, savedObjectsClient, esClient, + alertingRulesClient, spaceId, force: true, // upload has implicit force paths, @@ -931,7 +949,7 @@ export async function installPackage(args: InstallPackageParams): Promise Date: Thu, 10 Jul 2025 08:56:26 -0700 Subject: [PATCH 04/41] Establish steel thread for creating alert assets --- .../plugins/shared/fleet/kibana.jsonc | 14 ++-- .../services/epm/kibana/assets/install.ts | 65 +++++++++++++++++-- .../kibana/assets/install_with_streaming.ts | 2 + .../server/services/epm/packages/install.ts | 1 + .../steps/step_install_kibana_assets.ts | 13 +++- 5 files changed, 76 insertions(+), 19 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/kibana.jsonc b/x-pack/platform/plugins/shared/fleet/kibana.jsonc index e4139e517f107..f88bd25a3a133 100644 --- a/x-pack/platform/plugins/shared/fleet/kibana.jsonc +++ b/x-pack/platform/plugins/shared/fleet/kibana.jsonc @@ -1,20 +1,16 @@ { "type": "plugin", "id": "@kbn/fleet-plugin", - "owner": [ - "@elastic/fleet" - ], + "owner": ["@elastic/fleet"], "group": "platform", "visibility": "shared", "plugin": { "id": "fleet", "browser": true, "server": true, - "configPath": [ - "xpack", - "fleet" - ], + "configPath": ["xpack", "fleet"], "requiredPlugins": [ + "alerting", "licensing", "data", "encryptedSavedObjects", @@ -53,8 +49,6 @@ "usageCollection", "unifiedSearch" ], - "extraPublicDirs": [ - "common" - ] + "extraPublicDirs": ["common"] } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index f90c8579d39af..f1bfcc456533e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,8 +16,9 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -// import { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { TypeOf } from '@kbn/config-schema'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -56,10 +57,11 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; -type AlertRuleAsset = typeof alertRuleBodySchema & { +interface AlertRuleAsset { id: string; type: KibanaSavedObjectType.alert; -}; + template: Omit, 'actions'>; +} type SavedObjectAsset = Pick< SavedObject, | 'id' @@ -136,11 +138,18 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; kibanaAssetsArchiveIterator: ReturnType; }): Promise { - const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger } = options; + const { + kibanaAssetsArchiveIterator, + savedObjectsClient, + savedObjectsImporter, + alertingRulesClient, + logger, + } = options; let assetsToInstall: ArchiveAssetEntry[] = []; let res: SavedObjectsImportSuccess[] = []; @@ -177,7 +186,7 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - await installAlertRules({ logger, alertRuleAssets: asAlertRules }); + await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules }); const installedAssets = await installKibanaSavedObjects({ logger, @@ -239,6 +248,7 @@ export async function createDefaultIndexPatterns( export async function installKibanaAssetsAndReferencesMultispace({ savedObjectsClient, + alertingRulesClient, logger, pkgName, pkgTitle, @@ -249,6 +259,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -262,6 +273,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ // Install in every space => upgrades const refs = await installKibanaAssetsAndReferences({ savedObjectsClient, + alertingRulesClient, logger, pkgName, pkgTitle, @@ -277,6 +289,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ )) { await installKibanaAssetsAndReferences({ savedObjectsClient, + alertingRulesClient, logger, pkgName, pkgTitle, @@ -292,6 +305,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ return installKibanaAssetsAndReferences({ savedObjectsClient, + alertingRulesClient, logger, pkgName, pkgTitle, @@ -305,6 +319,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ export async function installKibanaAssetsAndReferences({ savedObjectsClient, + alertingRulesClient, logger, pkgName, pkgTitle, @@ -315,6 +330,7 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -338,6 +354,7 @@ export async function installKibanaAssetsAndReferences({ savedObjectsClient, logger, savedObjectsImporter, + alertingRulesClient, pkgName, kibanaAssetsArchiveIterator, }); @@ -637,11 +654,45 @@ function hasReferences(assetsToInstall: SavedObjectAsset[]) { async function installAlertRules({ logger, + alertingRulesClient, alertRuleAssets, }: { logger: Logger; + alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; }): Promise { - logger.debug(`no-op alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); - return Promise.resolve(); + logger.debug(`create alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); + const { template: alertRule, id } = alertRuleAssets[0]; + + const { + rule_type_id: _ruleTypeId, + alert_delay: _alertDelay, + notify_when: _notifyWhen, + ...baseCreateData + } = alertRule; + + const createData = { + ...baseCreateData, + alertTypeId: alertRule.rule_type_id, + flapping: alertRule.flapping + ? { + lookBackWindow: alertRule.flapping.look_back_window, + statusChangeThreshold: alertRule.flapping.status_change_threshold, + } + : undefined, + ...(alertRule.alert_delay ? { alertDelay: alertRule.alert_delay } : {}), + ...(alertRule.notify_when ? { notifyWhen: alertRule.notify_when } : {}), + actions: [], + }; + + try { + await alertingRulesClient.create({ data: createData, options: { id } }); + } catch (e) { + if (e?.output?.statusCode === 409) { + await alertingRulesClient.update({ + data: createData, + id, + }); + } + } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index b424d71b00f62..2941fbb78bc8a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -6,6 +6,7 @@ */ import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { PackageInstallContext } from '../../../../../common/types'; import type { KibanaAssetReference, KibanaAssetType } from '../../../../types'; @@ -28,6 +29,7 @@ interface InstallKibanaAssetsWithStreamingArgs { packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClient; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index f317d98a3e4e9..da0d45801b9ee 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -751,6 +751,7 @@ export async function installPackageWithStateMachine(options: { savedObjectTagAssignmentService, savedObjectTagClient, esClient, + alertingRulesClient, logger, installedPkg, packageInstallContext, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts index ba8f71123eb6d..0eb7c137fbd33 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts @@ -16,13 +16,21 @@ import { INSTALL_STATES } from '../../../../../../common/types'; import { installKibanaAssetsWithStreaming } from '../../../kibana/assets/install_with_streaming'; export async function stepInstallKibanaAssets(context: InstallContext) { - const { savedObjectsClient, logger, installedPkg, packageInstallContext, spaceId } = context; + const { + savedObjectsClient, + alertingRulesClient, + logger, + installedPkg, + packageInstallContext, + spaceId, + } = context; const { packageInfo } = packageInstallContext; const { name: pkgName, title: pkgTitle } = packageInfo; const kibanaAssetPromise = withPackageSpan('Install Kibana assets', () => installKibanaAssetsAndReferencesMultispace({ savedObjectsClient, + alertingRulesClient, pkgName, pkgTitle, packageInstallContext, @@ -40,7 +48,7 @@ export async function stepInstallKibanaAssets(context: InstallContext) { } export async function stepInstallKibanaAssetsWithStreaming(context: InstallContext) { - const { savedObjectsClient, packageInstallContext, spaceId } = context; + const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId } = context; const { packageInfo } = packageInstallContext; const { name: pkgName } = packageInfo; @@ -49,6 +57,7 @@ export async function stepInstallKibanaAssetsWithStreaming(context: InstallConte () => installKibanaAssetsWithStreaming({ savedObjectsClient, + alertingRulesClient, pkgName, packageInstallContext, spaceId, From a51e62fb4c1dd569ae3c3c7ef91ae48072cc3285 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 10 Jul 2025 13:55:58 -0700 Subject: [PATCH 05/41] Handle installing multiple alert assets --- .../services/epm/kibana/assets/alert_rules.ts | 121 ++++++++++++++++++ .../services/epm/kibana/assets/install.ts | 60 +-------- 2 files changed, 128 insertions(+), 53 deletions(-) create mode 100644 x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts new file mode 100644 index 0000000000000..b0c510f1ee789 --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -0,0 +1,121 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import { chunk } from 'lodash'; +import type { Logger } from '@kbn/core/server'; +import type { TypeOf } from '@kbn/config-schema'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; + +import type { KibanaSavedObjectType } from '../../../../types'; + +export interface AlertRuleAsset { + id: string; + type: KibanaSavedObjectType.alert; + template: Omit, 'actions'>; +} + +export async function installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets, + assetsChunkSize, +}: { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAssets: AlertRuleAsset[]; + assetsChunkSize?: number; +}) { + if (!assetsChunkSize || alertRuleAssets.length <= assetsChunkSize) { + return await installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets }); + } + + const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); + const results = []; + for (const alertRuleChunk of alertRuleChunks) { + const result = await installAlertRuleChunk({ + logger, + alertingRulesClient, + alertRuleAssets: alertRuleChunk, + }); + results.push(result); + } + + return results; +} + +async function installAlertRuleChunk({ + logger, + alertingRulesClient, + alertRuleAssets, +}: { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAssets: AlertRuleAsset[]; +}) { + const alertRuleInstalls = alertRuleAssets.map((alertRuleAsset) => { + return installAlertRule({ logger, alertingRulesClient, alertRuleAsset }); + }); + + return await Promise.allSettled(alertRuleInstalls); +} + +async function installAlertRule({ + logger, + alertingRulesClient, + alertRuleAsset, +}: { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAsset: AlertRuleAsset; +}) { + const { template: alertRule, id } = alertRuleAsset; + + const createData = transformToCreateAlertRule(alertRule); + + try { + const result = await alertingRulesClient.create({ data: createData, options: { id } }); + return result; + } catch (e) { + // Already exists + if (e?.output?.statusCode === 409) { + const result = await alertingRulesClient.update({ + data: createData, + id, + }); + return result; + } + throw e; + } +} + +function transformToCreateAlertRule(template: AlertRuleAsset['template']) { + const { + rule_type_id: _ruleTypeId, + alert_delay: _alertDelay, + notify_when: _notifyWhen, + ...baseCreateData + } = template; + + return { + ...baseCreateData, + // Always disabled + enabled: false, + alertTypeId: template.rule_type_id, + flapping: template.flapping + ? { + lookBackWindow: template.flapping.look_back_window, + statusChangeThreshold: template.flapping.status_change_threshold, + } + : undefined, + ...(template.alert_delay ? { alertDelay: template.alert_delay } : {}), + ...(template.notify_when ? { notifyWhen: template.notify_when } : {}), + // Always include 'Managed' tag + tags: [...new Set([...template.tags, 'Managed'])], + // Always no prescribed actions + actions: [], + }; +} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index f1bfcc456533e..d8971bd37689e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,8 +16,6 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -import type { TypeOf } from '@kbn/config-schema'; -import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -40,6 +38,7 @@ import { appContextService } from '../../..'; import { tagKibanaAssets } from './tag_assets'; import { getSpaceAwareSaveobjectsClients } from './saved_objects'; +import { installAlertRules, type AlertRuleAsset } from './alert_rules'; const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 200; @@ -57,11 +56,6 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; -interface AlertRuleAsset { - id: string; - type: KibanaSavedObjectType.alert; - template: Omit, 'actions'>; -} type SavedObjectAsset = Pick< SavedObject, | 'id' @@ -186,7 +180,12 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules }); + await installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets: asAlertRules, + assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, + }); const installedAssets = await installKibanaSavedObjects({ logger, @@ -651,48 +650,3 @@ export function toAssetReference({ id, type }: SavedObject) { function hasReferences(assetsToInstall: SavedObjectAsset[]) { return assetsToInstall.some((asset) => asset.references.length); } - -async function installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets, -}: { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAssets: AlertRuleAsset[]; -}): Promise { - logger.debug(`create alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); - const { template: alertRule, id } = alertRuleAssets[0]; - - const { - rule_type_id: _ruleTypeId, - alert_delay: _alertDelay, - notify_when: _notifyWhen, - ...baseCreateData - } = alertRule; - - const createData = { - ...baseCreateData, - alertTypeId: alertRule.rule_type_id, - flapping: alertRule.flapping - ? { - lookBackWindow: alertRule.flapping.look_back_window, - statusChangeThreshold: alertRule.flapping.status_change_threshold, - } - : undefined, - ...(alertRule.alert_delay ? { alertDelay: alertRule.alert_delay } : {}), - ...(alertRule.notify_when ? { notifyWhen: alertRule.notify_when } : {}), - actions: [], - }; - - try { - await alertingRulesClient.create({ data: createData, options: { id } }); - } catch (e) { - if (e?.output?.statusCode === 409) { - await alertingRulesClient.update({ - data: createData, - id, - }); - } - } -} From 14b2df6314f4fde71ac317c5bce2377127b8779c Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Fri, 11 Jul 2025 08:02:33 -0700 Subject: [PATCH 06/41] Include alert rules in pkg install results, support baseline tags --- .../services/epm/kibana/assets/alert_rules.ts | 103 ++++++++++++++---- .../services/epm/kibana/assets/install.ts | 34 ++++-- .../services/epm/kibana/assets/tag_assets.ts | 19 ++-- 3 files changed, 113 insertions(+), 43 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index b0c510f1ee789..e4186a39e9e39 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -10,7 +10,9 @@ import type { TypeOf } from '@kbn/config-schema'; import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; -import type { KibanaSavedObjectType } from '../../../../types'; +import { KibanaSavedObjectType, type PackageSpecTags } from '../../../../types'; + +import { getManagedTagId, getPackageTagId } from './tag_assets'; export interface AlertRuleAsset { id: string; @@ -18,46 +20,83 @@ export interface AlertRuleAsset { template: Omit, 'actions'>; } +interface ObjectReference { + type: string; + id: string; +} + +interface InstallAlertRulesParamsContext { + pkgName: string; + spaceId: string; + assetTags?: PackageSpecTags[]; +} + +interface InstallAlertRulesParams { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAssets: AlertRuleAsset[]; + context: InstallAlertRulesParamsContext; + assetsChunkSize?: number; +} + export async function installAlertRules({ logger, alertingRulesClient, alertRuleAssets, + context, assetsChunkSize, -}: { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAssets: AlertRuleAsset[]; - assetsChunkSize?: number; -}) { - if (!assetsChunkSize || alertRuleAssets.length <= assetsChunkSize) { - return await installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets }); - } +}: InstallAlertRulesParams): Promise { + let results: Array> = []; - const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); - const results = []; - for (const alertRuleChunk of alertRuleChunks) { - const result = await installAlertRuleChunk({ + if (!assetsChunkSize || alertRuleAssets.length <= assetsChunkSize) { + results = await installAlertRuleChunk({ logger, alertingRulesClient, - alertRuleAssets: alertRuleChunk, + alertRuleAssets, + context, }); - results.push(result); + } else { + const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); + + for (const alertRuleChunk of alertRuleChunks) { + const result = await installAlertRuleChunk({ + logger, + alertingRulesClient, + alertRuleAssets: alertRuleChunk, + context, + }); + results = [...results, ...result]; + } } - return results; + const { successes, errors } = getSuccessesAndErrors(results); + + if (errors.length > 0) { + throw new Error( + `Encountered ${errors.length} errors installing alert rule assets: ${JSON.stringify( + errors, + null, + 2 + )}` + ); + } + + return successes; } async function installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets, + context, }: { logger: Logger; alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; + context: InstallAlertRulesParamsContext; }) { const alertRuleInstalls = alertRuleAssets.map((alertRuleAsset) => { - return installAlertRule({ logger, alertingRulesClient, alertRuleAsset }); + return installAlertRule({ logger, alertingRulesClient, alertRuleAsset, context }); }); return await Promise.allSettled(alertRuleInstalls); @@ -67,18 +106,21 @@ async function installAlertRule({ logger, alertingRulesClient, alertRuleAsset, + context: { pkgName, spaceId, assetTags }, }: { logger: Logger; alertingRulesClient: RulesClient; alertRuleAsset: AlertRuleAsset; + context: InstallAlertRulesParamsContext; }) { const { template: alertRule, id } = alertRuleAsset; + const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; - const createData = transformToCreateAlertRule(alertRule); + const createData = transformToCreateAlertRule(alertRule, tags); try { const result = await alertingRulesClient.create({ data: createData, options: { id } }); - return result; + return { id: result.id, type: KibanaSavedObjectType.alert }; } catch (e) { // Already exists if (e?.output?.statusCode === 409) { @@ -86,13 +128,13 @@ async function installAlertRule({ data: createData, id, }); - return result; + return { id: result.id, type: KibanaSavedObjectType.alert }; } throw e; } } -function transformToCreateAlertRule(template: AlertRuleAsset['template']) { +function transformToCreateAlertRule(template: AlertRuleAsset['template'], tags: string[]) { const { rule_type_id: _ruleTypeId, alert_delay: _alertDelay, @@ -113,9 +155,22 @@ function transformToCreateAlertRule(template: AlertRuleAsset['template']) { : undefined, ...(template.alert_delay ? { alertDelay: template.alert_delay } : {}), ...(template.notify_when ? { notifyWhen: template.notify_when } : {}), - // Always include 'Managed' tag - tags: [...new Set([...template.tags, 'Managed'])], // Always no prescribed actions actions: [], + tags: [...new Set([...baseCreateData.tags, ...tags])], }; } + +function getSuccessesAndErrors(results: Array>) { + return results.reduce<{ successes: ObjectReference[]; errors: string[] }>( + (acc, result) => { + if (result.status === 'fulfilled') { + acc.successes = [...acc.successes, result.value]; + } else { + acc.errors = [...acc.errors, result.reason]; + } + return acc; + }, + { successes: [], errors: [] } + ); +} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index d8971bd37689e..6d2fe50eacc77 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -24,6 +24,7 @@ import { getPathParts } from '../../archive'; import { KibanaAssetType, KibanaSavedObjectType } from '../../../../types'; import type { AssetReference, Installation, PackageSpecTags } from '../../../../types'; import type { KibanaAssetReference, PackageInstallContext } from '../../../../../common/types'; +import { MAX_CONCURRENT_PACKAGE_ASSETS } from '../../../../constants'; import { indexPatternTypes, getIndexPatternSavedObjects, @@ -42,6 +43,11 @@ import { installAlertRules, type AlertRuleAsset } from './alert_rules'; const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 200; +interface ObjectReference { + type: string; + id: string; +} + type SavedObjectsImporterContract = Pick; const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => JSON.stringify( @@ -135,18 +141,23 @@ export async function installKibanaAssets(options: { alertingRulesClient: RulesClient; logger: Logger; pkgName: string; + spaceId: string; + assetTags?: PackageSpecTags[]; kibanaAssetsArchiveIterator: ReturnType; -}): Promise { +}): Promise> { const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, alertingRulesClient, logger, + pkgName, + spaceId, + assetTags, } = options; let assetsToInstall: ArchiveAssetEntry[] = []; - let res: SavedObjectsImportSuccess[] = []; + let res: Array = []; const installManagedIndexPatternOnce = once(() => installManagedIndexPattern({ @@ -160,7 +171,7 @@ export async function installKibanaAssets(options: { asAlertRules: AlertRuleAsset[]; } const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { - return assetsToInstall.reduce( + return assetEntries.reduce( (installGroups, assetEntry) => { if (assetEntry.assetType === KibanaAssetType.alert) { installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; @@ -180,11 +191,12 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - await installAlertRules({ + const installedAlertRules = await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules, - assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, + assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, + context: { pkgName, spaceId, assetTags }, }); const installedAssets = await installKibanaSavedObjects({ @@ -194,7 +206,7 @@ export async function installKibanaAssets(options: { assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); assetsToInstall = []; - res = [...res, ...installedAssets]; + res = [...res, ...installedAssets, ...installedAlertRules]; } await kibanaAssetsArchiveIterator(async (entry) => { @@ -355,14 +367,16 @@ export async function installKibanaAssetsAndReferences({ savedObjectsImporter, alertingRulesClient, pkgName, + spaceId, + assetTags, kibanaAssetsArchiveIterator, }); const assets = importedAssets.map( - ({ id, type, destinationId }) => + (asset) => ({ - id: destinationId ?? id, - ...(destinationId ? { originId: id } : {}), - type, + id: 'destinationId' in asset && asset.destinationId ? asset.destinationId : asset.id, + ...('destinationId' in asset && asset.destinationId ? { originId: asset.id } : {}), + type: asset.type, } as KibanaAssetReference) ); installedKibanaAssetsRefs = await saveKibanaAssetsRefs( diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts index bebc0ba9dc810..34328284e3ce4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts @@ -55,8 +55,9 @@ const TAG_COLORS = [ '#A0A0A0', ]; -const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; -const getPackageTagId = (spaceId: string, pkgName: string) => `fleet-pkg-${pkgName}-${spaceId}`; +export const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; +export const getPackageTagId = (spaceId: string, pkgName: string) => + `fleet-pkg-${pkgName}-${spaceId}`; const getLegacyPackageTagId = (pkgName: string) => pkgName; /* @@ -85,12 +86,12 @@ interface TagAssetsParams { pkgTitle: string; pkgName: string; spaceId: string; - importedAssets: SavedObjectsImportSuccess[]; + importedAssets: Array; assetTags?: PackageSpecTags[]; } -const getNewId = (asset: SavedObjectsImportSuccess) => - asset?.destinationId ? asset.destinationId : asset.id; +const getNewId = (asset: ObjectReference | SavedObjectsImportSuccess) => + 'destinationId' in asset && asset?.destinationId ? asset.destinationId : asset.id; export async function tagKibanaAssets(opts: TagAssetsParams) { const { savedObjectTagAssignmentService, importedAssets } = opts; @@ -147,7 +148,7 @@ export async function tagKibanaAssets(opts: TagAssetsParams) { } } -function getTaggableAssets(importedAssets: SavedObjectsImportSuccess[]) { +function getTaggableAssets(importedAssets: Array) { return importedAssets.filter((asset) => taggableTypes.includes(asset.type)); } @@ -206,7 +207,7 @@ async function ensurePackageTag( // Ensure that asset tags coming from the kibana/tags.yml file are correctly parsed and created async function getPackageSpecTags( - taggableAssets: SavedObjectsImportSuccess[], + taggableAssets: Array, opts: Pick ): Promise { const { spaceId, savedObjectTagClient, pkgName, assetTags } = opts; @@ -241,7 +242,7 @@ async function getPackageSpecTags( // Get all the assets of types defined in tag.asset_types from taggable kibanaAssets const getAssetTypesObjectReferences = ( assetTypes: string[] | undefined, - taggableAssets: SavedObjectsImportSuccess[] + taggableAssets: Array ): ObjectReference[] => { if (!assetTypes || assetTypes.length === 0) return []; @@ -255,7 +256,7 @@ const getAssetTypesObjectReferences = ( // Get the references to ids defined in tag.asset_ids from taggable kibanaAssets const getAssetIdsObjectReferences = ( assetIds: string[] | undefined, - taggableAssets: SavedObjectsImportSuccess[] + taggableAssets: Array ): ObjectReference[] => { if (!assetIds || assetIds.length === 0) return []; From 243e55c151ac43b3a45818061bae114090da643e Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Fri, 11 Jul 2025 08:47:09 -0700 Subject: [PATCH 07/41] Support asset tags for alert rules --- .../services/epm/kibana/assets/alert_rules.ts | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index e4186a39e9e39..2a940baca8618 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -106,7 +106,7 @@ async function installAlertRule({ logger, alertingRulesClient, alertRuleAsset, - context: { pkgName, spaceId, assetTags }, + context, }: { logger: Logger; alertingRulesClient: RulesClient; @@ -114,7 +114,7 @@ async function installAlertRule({ context: InstallAlertRulesParamsContext; }) { const { template: alertRule, id } = alertRuleAsset; - const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; + const tags = getTags(id, context); const createData = transformToCreateAlertRule(alertRule, tags); @@ -161,6 +161,24 @@ function transformToCreateAlertRule(template: AlertRuleAsset['template'], tags: }; } +function getTags(id: string, context: InstallAlertRulesParamsContext) { + const { pkgName, spaceId, assetTags } = context; + const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; + + if (!assetTags || assetTags.length === 0) { + return tags; + } + + const filteredAssetTags = assetTags.reduce((_assetTags, assetTag) => { + if (assetTag.asset_types?.includes('alert') || assetTag.asset_ids?.includes(id)) { + return [..._assetTags, assetTag.text]; + } + return _assetTags; + }, []); + + return [...tags, ...filteredAssetTags]; +} + function getSuccessesAndErrors(results: Array>) { return results.reduce<{ successes: ObjectReference[]; errors: string[] }>( (acc, result) => { From baf108f956380e83490e46e9118f89aed4aaf865 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Mon, 14 Jul 2025 11:38:44 -0700 Subject: [PATCH 08/41] Support bulk uninstall of alert rules --- .../fleet/server/routes/epm/handlers.ts | 4 ++ .../services/epm/kibana/assets/alert_rules.ts | 8 +-- .../services/epm/kibana/assets/install.ts | 24 ++++++--- .../server/services/epm/packages/install.ts | 24 +++++---- .../_state_machine_package_install.ts | 2 + .../server/services/epm/packages/remove.ts | 54 ++++++++++++++++--- 6 files changed, 91 insertions(+), 25 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts index 979e694fa5657..7047964671b41 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts @@ -540,8 +540,12 @@ export const deletePackageHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const res = await removeInstallation({ savedObjectsClient, + alertingRulesClient, pkgName, pkgVersion, esClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index 2a940baca8618..fe5e8c9e381b6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -7,7 +7,7 @@ import { chunk } from 'lodash'; import type { Logger } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import { KibanaSavedObjectType, type PackageSpecTags } from '../../../../types'; @@ -33,7 +33,7 @@ interface InstallAlertRulesParamsContext { interface InstallAlertRulesParams { logger: Logger; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; alertRuleAssets: AlertRuleAsset[]; context: InstallAlertRulesParamsContext; assetsChunkSize?: number; @@ -91,7 +91,7 @@ async function installAlertRuleChunk({ context, }: { logger: Logger; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; alertRuleAssets: AlertRuleAsset[]; context: InstallAlertRulesParamsContext; }) { @@ -109,7 +109,7 @@ async function installAlertRule({ context, }: { logger: Logger; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; alertRuleAsset: AlertRuleAsset; context: InstallAlertRulesParamsContext; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 6d2fe50eacc77..4985d0e5b2c97 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,7 +16,7 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -138,7 +138,7 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; spaceId: string; @@ -270,7 +270,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; pkgTitle: string; @@ -341,7 +341,7 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; pkgTitle: string; @@ -357,7 +357,12 @@ export async function installKibanaAssetsAndReferences({ const kibanaAssetsArchiveIterator = getKibanaAssetsArchiveIterator(packageInstallContext); if (installedPkg) { - await deleteKibanaSavedObjectsAssets({ savedObjectsClient, installedPkg, spaceId }); + await deleteKibanaSavedObjectsAssets({ + savedObjectsClient, + alertingRulesClient, + installedPkg, + spaceId, + }); } let installedKibanaAssetsRefs: KibanaAssetReference[] = []; @@ -405,12 +410,14 @@ export async function installKibanaAssetsAndReferences({ export async function deleteKibanaAssetsAndReferencesForSpace({ savedObjectsClient, + alertingRulesClient, logger, pkgName, installedPkg, spaceId, }: { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; installedPkg: SavedObject; @@ -425,7 +432,12 @@ export async function deleteKibanaAssetsAndReferencesForSpace({ 'Impossible to delete kibana assets from the space where the package was installed, you must uninstall the package.' ); } - await deleteKibanaSavedObjectsAssets({ savedObjectsClient, installedPkg, spaceId }); + await deleteKibanaSavedObjectsAssets({ + savedObjectsClient, + alertingRulesClient, + installedPkg, + spaceId, + }); await saveKibanaAssetsRefs(savedObjectsClient, pkgName, null, true); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index da0d45801b9ee..d96aed266e310 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -21,7 +21,7 @@ import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import pRetry from 'p-retry'; import type { LicenseType } from '@kbn/licensing-plugin/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { KibanaAssetReference, @@ -175,7 +175,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -285,7 +285,7 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -327,7 +327,13 @@ export async function handleInstallPackageFailure({ if (keepFailedInstallation) { return; } - await removeInstallation({ savedObjectsClient, pkgName, pkgVersion, esClient }); + await removeInstallation({ + savedObjectsClient, + alertingRulesClient, + pkgName, + pkgVersion, + esClient, + }); return; } @@ -402,7 +408,7 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -426,7 +432,7 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -435,7 +441,7 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -619,7 +625,7 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -1335,7 +1341,7 @@ export const saveKibanaAssetsRefs = async ( export async function ensurePackagesCompletedInstall( savedObjectsClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClient + alertingRulesClient: RulesClientApi ) { const installingPackages = await getPackageSavedObjects(savedObjectsClient, { searchFields: ['install_status'], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts index c941b6d60d63b..bc4c72cdf38ca 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts @@ -11,6 +11,7 @@ import type { SavedObjectsClientContract, } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { PackageSavedObjectConflictError } from '../../../../errors'; @@ -61,6 +62,7 @@ import { handleState } from './state_machine'; export interface InstallContext extends StateContext { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi; esClient: ElasticsearchClient; logger: Logger; installedPkg?: SavedObject; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 18b5fe75d9961..18826d970a1b8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -6,11 +6,11 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import { differenceBy, chunk } from 'lodash'; +import { differenceBy, chunk, partition } from 'lodash'; import type { SavedObject } from '@kbn/core/server'; - import { SavedObjectsClient } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; @@ -60,13 +60,14 @@ const MAX_ASSETS_TO_DELETE = 1000; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi; pkgName: string; pkgVersion?: string; esClient: ElasticsearchClient; force?: boolean; installSource?: InstallSource; }): Promise { - const { savedObjectsClient, pkgName, pkgVersion, esClient } = options; + const { savedObjectsClient, alertingRulesClient, pkgName, pkgVersion, esClient } = options; const installation = await getInstallation({ savedObjectsClient, pkgName }); if (!installation) { throw new PackageRemovalError(`${pkgName} is not installed`); @@ -103,7 +104,7 @@ export async function removeInstallation(options: { // Delete the installed assets. Don't include installation.package_assets. Those are irrelevant to users const installedAssets = [...installation.installed_kibana, ...installation.installed_es]; - await deleteAssets(savedObjectsClient, installation, esClient); + await deleteAssets(savedObjectsClient, alertingRulesClient, installation, esClient); // Delete the manager saved object with references to the asset objects // could also update with [] or some other state @@ -144,11 +145,13 @@ export async function removeInstallation(options: { */ export async function deleteKibanaAssets({ installedObjects, + alertingRulesClient, packageSpecConditions, logger, spaceId = DEFAULT_SPACE_ID, }: { installedObjects: KibanaAssetReference[]; + alertingRulesClient: RulesClientApi; logger: Logger; packageSpecConditions?: PackageSpecConditions; spaceId?: string; @@ -170,8 +173,16 @@ export async function deleteKibanaAssets({ // only in 8.x or later. If so, we can skip SO resolution step altogether // and delete the assets directly. Otherwise, we need to resolve the assets // which might create high memory pressure if a package has a lot of assets. + const [alertAssets, soAssets] = partition( + installedObjects, + (installedObject) => installedObject.type === 'alert' + ); + if (minKibana && minKibana.major >= 8) { - await bulkDeleteSavedObjects(installedObjects, namespace, savedObjectsClient, logger); + await Promise.all([ + bulkDeleteSavedObjects(soAssets, namespace, savedObjectsClient, logger), + bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger), + ]); } else { const { resolved_objects: resolvedObjects } = await savedObjectsClient.bulkResolve( installedObjects, @@ -223,6 +234,30 @@ async function bulkDeleteSavedObjects( } } +async function bulkDeleteAlertRules( + alertRulesToDelete: Array<{ id: string; type: string }>, + alertingRulesClient: RulesClientApi, + logger: Logger +) { + logger.debug(`Starting bulk deletion of alert rules`); + for (const alertRule of alertRulesToDelete) { + logger.debug(`Delete asset - id: ${alertRule?.id}, type: ${alertRule?.type},`); + auditLoggingService.writeCustomSoAuditLog({ + action: 'delete', + id: alertRule.id, + savedObjectType: alertRule.type, + }); + } + // Delete alert rules in chunks to avoid high memory pressure. This is mostly + // relevant for packages containing many assets, as large payload and response + // objects are created in memory during the delete operation. While chunking + // may work slower, it allows garbage collection to clean up memory between + // requests. + for (const alertRulesChunk of chunk(alertRulesToDelete, MAX_ASSETS_TO_DELETE)) { + await alertingRulesClient.bulkDeleteRules({ ids: alertRulesChunk.map(({ id }) => id) }); + } +} + export const deleteESAsset = async ( installedObject: EsAssetReference, esClient: ElasticsearchClient @@ -340,6 +375,7 @@ export async function deletePrerequisiteAssets( async function deleteAssets( savedObjectsClient: SavedObjectsClientContract, + alertingRulesClient: RulesClientApi, { installed_es: installedEs, installed_kibana: installedKibana, @@ -378,6 +414,7 @@ async function deleteAssets( ...deleteESAssets(otherAssets, esClient), deleteKibanaAssets({ installedObjects: installedKibana, + alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, @@ -385,6 +422,7 @@ async function deleteAssets( Object.entries(installedInAdditionalSpacesKibana).map(([additionalSpaceId, kibanaAssets]) => deleteKibanaAssets({ installedObjects: kibanaAssets, + alertingRulesClient, spaceId: additionalSpaceId, logger, packageSpecConditions: packageInfo?.conditions, @@ -423,10 +461,12 @@ async function deleteComponentTemplate(esClient: ElasticsearchClient, name: stri export async function deleteKibanaSavedObjectsAssets({ savedObjectsClient, + alertingRulesClient, installedPkg, spaceId, }: { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi; installedPkg: SavedObject; spaceId?: string; }) { @@ -458,6 +498,7 @@ export async function deleteKibanaSavedObjectsAssets({ await deleteKibanaAssets({ installedObjects: assetsToDelete, + alertingRulesClient, spaceId: spaceIdToDelete, packageSpecConditions: packageInfo?.conditions, logger, @@ -525,9 +566,10 @@ export async function cleanupAssets( installationToDelete: Installation, originalInstallation: Installation, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, soClient: SavedObjectsClientContract ) { - await deleteAssets(soClient, installationToDelete, esClient); + await deleteAssets(soClient, alertingRulesClient, installationToDelete, esClient); const { installed_es: installedEs, From 969f3af46c082f521319eb06bb0a1fb13cb898a6 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Mon, 14 Jul 2025 14:15:08 -0700 Subject: [PATCH 09/41] Support alert rules in streaming package install --- .../services/epm/kibana/assets/install.ts | 43 +++++++------- .../kibana/assets/install_with_streaming.ts | 59 +++++++++++++++---- .../steps/step_install_kibana_assets.ts | 17 +++++- .../server/services/epm/packages/remove.ts | 4 +- 4 files changed, 84 insertions(+), 39 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 4985d0e5b2c97..1b0b5d2377304 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -62,7 +62,7 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; -type SavedObjectAsset = Pick< +export type SavedObjectAsset = Pick< SavedObject, | 'id' | 'attributes' @@ -166,25 +166,6 @@ export async function installKibanaAssets(options: { }) ); - interface InstallGroups { - asSavedObjects: SavedObjectAsset[]; - asAlertRules: AlertRuleAsset[]; - } - const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { - return assetEntries.reduce( - (installGroups, assetEntry) => { - if (assetEntry.assetType === KibanaAssetType.alert) { - installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; - return installGroups; - } - - installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; - return installGroups; - }, - { asSavedObjects: [], asAlertRules: [] } - ); - }; - async function flushAssetsToInstall() { await installManagedIndexPatternOnce(); @@ -667,7 +648,7 @@ function removeReservedIndexPatterns(kibanaAssets: ArchiveAssetEntry[]) { return kibanaAssets.filter((assetEntry) => !reservedPatterns.includes(assetEntry.asset.id)); } -export function toAssetReference({ id, type }: SavedObject) { +export function toAssetReference({ id, type }: ArchiveAsset) { const reference: AssetReference = { id, type: type as KibanaSavedObjectType }; return reference; @@ -676,3 +657,23 @@ export function toAssetReference({ id, type }: SavedObject) { function hasReferences(assetsToInstall: SavedObjectAsset[]) { return assetsToInstall.some((asset) => asset.references.length); } + +interface InstallGroups { + asSavedObjects: SavedObjectAsset[]; + asAlertRules: AlertRuleAsset[]; +} + +export function createInstallGroups(assetEntries: ArchiveAssetEntry[]) { + return assetEntries.reduce( + (installGroups, assetEntry) => { + if (assetEntry.assetType === KibanaAssetType.alert) { + installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; + return installGroups; + } + + installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; + return installGroups; + }, + { asSavedObjects: [], asAlertRules: [] } + ); +} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index 2941fbb78bc8a..f24e2107a022a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -5,16 +5,17 @@ * 2.0. */ -import type { SavedObjectsClientContract } from '@kbn/core/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; +import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import { MAX_CONCURRENT_PACKAGE_ASSETS } from '../../../../constants'; import type { PackageInstallContext } from '../../../../../common/types'; -import type { KibanaAssetReference, KibanaAssetType } from '../../../../types'; +import { type KibanaAssetReference, KibanaAssetType } from '../../../../types'; import { getPathParts } from '../../archive'; import { saveKibanaAssetsRefs } from '../../packages/install'; -import type { ArchiveAsset } from './install'; +import type { ArchiveAsset, SavedObjectAsset } from './install'; import { KibanaSavedObjectTypeMapping, createSavedObjectKibanaAsset, @@ -23,20 +24,24 @@ import { toAssetReference, } from './install'; import { getSpaceAwareSaveobjectsClients } from './saved_objects'; +import { installAlertRules, type AlertRuleAsset } from './alert_rules'; interface InstallKibanaAssetsWithStreamingArgs { + logger: Logger; pkgName: string; packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; + alertingRulesClient: RulesClientApi; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; export async function installKibanaAssetsWithStreaming({ + logger, spaceId, packageInstallContext, + alertingRulesClient, savedObjectsClient, pkgName, }: InstallKibanaAssetsWithStreamingArgs): Promise { @@ -50,8 +55,10 @@ export async function installKibanaAssetsWithStreaming({ savedObjectsClient, }); + const assetTags = packageInstallContext.packageInfo?.asset_tags; const assetRefs: KibanaAssetReference[] = []; - let batch: ArchiveAsset[] = []; + let savedObjectBatch: SavedObjectAsset[] = []; + let alertRuleBatch: AlertRuleAsset[] = []; await archiveIterator.traverseEntries(async ({ path, buffer }) => { if (!buffer || !isKibanaAssetType(path)) { @@ -64,29 +71,55 @@ export async function installKibanaAssetsWithStreaming({ return; } - batch.push(savedObject); + if (assetType === KibanaAssetType.alert) { + alertRuleBatch.push(savedObject as AlertRuleAsset); + } else { + savedObjectBatch.push(savedObject as SavedObjectAsset); + } + assetRefs.push(toAssetReference(savedObject)); - if (batch.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { + if (savedObjectBatch.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, - kibanaAssets: batch, + kibanaAssets: savedObjectBatch, refresh: false, }); - batch = []; + savedObjectBatch = []; } }); + if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS) { + await installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets: alertRuleBatch, + assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, + context: { pkgName, spaceId, assetTags }, + }); + alertRuleBatch = []; + } + // install any remaining assets - if (batch.length) { + if (savedObjectBatch.length) { await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, - kibanaAssets: batch, + kibanaAssets: savedObjectBatch, // Use wait_for with the last batch to ensure all assets are readable once the install is complete refresh: 'wait_for', }); } + if (alertRuleBatch.length) { + await installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets: alertRuleBatch, + assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, + context: { pkgName, spaceId, assetTags }, + }); + } + // Update the installation saved object with installed kibana assets await saveKibanaAssetsRefs(savedObjectsClient, pkgName, assetRefs); @@ -98,7 +131,7 @@ async function bulkCreateSavedObjects({ kibanaAssets, refresh, }: { - kibanaAssets: ArchiveAsset[]; + kibanaAssets: SavedObjectAsset[]; savedObjectsClient: SavedObjectsClientContract; refresh?: boolean | 'wait_for'; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts index 0eb7c137fbd33..3068d1c70e6a8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts @@ -48,7 +48,8 @@ export async function stepInstallKibanaAssets(context: InstallContext) { } export async function stepInstallKibanaAssetsWithStreaming(context: InstallContext) { - const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId } = context; + const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId, logger } = + context; const { packageInfo } = packageInstallContext; const { name: pkgName } = packageInfo; @@ -61,6 +62,7 @@ export async function stepInstallKibanaAssetsWithStreaming(context: InstallConte pkgName, packageInstallContext, spaceId, + logger, }) ); @@ -71,6 +73,7 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { const { logger, installedPkg, + alertingRulesClient, packageInstallContext, spaceId, retryFromLastState, @@ -93,6 +96,7 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { await withPackageSpan('Retry transition - clean up Kibana assets first', async () => { await deleteKibanaAssets({ installedObjects, + alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, @@ -112,8 +116,14 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { * */ export async function cleanUpUnusedKibanaAssetsStep(context: InstallContext) { - const { logger, installedPkg, packageInstallContext, spaceId, installedKibanaAssetsRefs } = - context; + const { + logger, + installedPkg, + packageInstallContext, + spaceId, + installedKibanaAssetsRefs, + alertingRulesClient, + } = context; const { packageInfo } = packageInstallContext; if (!installedKibanaAssetsRefs) { @@ -140,6 +150,7 @@ export async function cleanUpUnusedKibanaAssetsStep(context: InstallContext) { await withPackageSpan('Clean up Kibana assets that are no longer in the package', async () => { await deleteKibanaAssets({ installedObjects: assetsToRemove, + alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 18826d970a1b8..8dd71e10b195a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -28,7 +28,7 @@ import { SO_SEARCH_LIMIT, USER_SETTINGS_TEMPLATE_SUFFIX, } from '../../../constants'; -import { ElasticsearchAssetType } from '../../../types'; +import { ElasticsearchAssetType, KibanaSavedObjectType } from '../../../types'; import type { AssetReference, AssetType, @@ -175,7 +175,7 @@ export async function deleteKibanaAssets({ // which might create high memory pressure if a package has a lot of assets. const [alertAssets, soAssets] = partition( installedObjects, - (installedObject) => installedObject.type === 'alert' + (installedObject) => installedObject.type === KibanaSavedObjectType.alert ); if (minKibana && minKibana.major >= 8) { From 518bf2a933798184ec9450d3ba7821735bd3eabd Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Mon, 14 Jul 2025 15:11:19 -0700 Subject: [PATCH 10/41] Fix unit tests --- .../server/services/epm/packages/remove.test.ts | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts index fcccb1fd6a6be..7c73f6fb7a3ac 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts @@ -47,6 +47,7 @@ const mockPackagePolicyService = packagePolicyService as jest.Mocked { let soClientMock: any; const esClientMock = {} as any; + let alertingRulesClientMock: any; beforeEach(() => { soClientMock = { get: jest.fn().mockResolvedValue({ attributes: { installed_kibana: [], installed_es: [] } }), @@ -55,6 +56,9 @@ describe('removeInstallation', () => { find: jest.fn().mockResolvedValue({ saved_objects: [] }), bulkResolve: jest.fn().mockResolvedValue({ resolved_objects: [] }), } as any; + alertingRulesClientMock = { + bulkDeleteRules: jest.fn().mockResolvedValue({}), + }; }); it('should remove package policies when force', async () => { await removeInstallation({ @@ -62,6 +66,7 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, + alertingRulesClient: alertingRulesClientMock, force: true, }); expect(mockPackagePolicyService.delete).toHaveBeenCalledWith( @@ -79,6 +84,7 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, + alertingRulesClient: alertingRulesClientMock, force: false, }) ).rejects.toThrowError( @@ -92,6 +98,7 @@ describe('removeInstallation', () => { pkgName: 'elastic_agent', pkgVersion: '1.0.0', esClient: esClientMock, + alertingRulesClient: alertingRulesClientMock, force: false, }); expect(mockPackagePolicyService.delete).toHaveBeenCalledTimes(2); @@ -103,6 +110,7 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, + alertingRulesClient: alertingRulesClientMock, force: true, }); @@ -148,6 +156,7 @@ describe('deleteESAsset', () => { describe('cleanupAssets', () => { let soClientMock: any; const esClientMock = {} as any; + let alertingRulesClientMock: any; beforeEach(() => { soClientMock = { get: jest @@ -165,6 +174,9 @@ describe('deleteESAsset', () => { find: jest.fn().mockResolvedValue({ saved_objects: [] }), bulkResolve: jest.fn().mockResolvedValue({ resolved_objects: [] }), } as any; + alertingRulesClientMock = { + bulkDeleteRules: jest.fn().mockResolvedValue({}), + }; }); it('should remove assets marked for deletion', async () => { @@ -216,6 +228,7 @@ describe('deleteESAsset', () => { installationToDelete, installation, esClientMock, + alertingRulesClientMock, soClientMock ); From 47ded3c2d0d9bf3a542922724643e66070c44c7e Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 15 Jul 2025 16:11:40 +0000 Subject: [PATCH 11/41] [CI] Auto-commit changed files from 'node scripts/yarn_deduplicate' --- x-pack/platform/plugins/shared/fleet/tsconfig.json | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/tsconfig.json b/x-pack/platform/plugins/shared/fleet/tsconfig.json index 67c33cc922652..556e1262be0dc 100644 --- a/x-pack/platform/plugins/shared/fleet/tsconfig.json +++ b/x-pack/platform/plugins/shared/fleet/tsconfig.json @@ -1,13 +1,9 @@ { "extends": "../../../../../tsconfig.base.json", "compilerOptions": { - "outDir": "target/types", + "outDir": "target/types" }, - "exclude": [ - "cypress.config.ts", - "cypress.config.space_awareness.ts", - "target/**/*", - ], + "exclude": ["cypress.config.ts", "cypress.config.space_awareness.ts", "target/**/*"], "include": [ // add all the folders containing files to be compiled ".storybook/**/*", @@ -126,5 +122,6 @@ "@kbn/logs-data-access-plugin", "@kbn/embeddable-plugin", "@kbn/core-chrome-layout-constants", + "@kbn/alerting-plugin" ] } From c22d07b720ce13bd4cae98b551b4491d8d2fdffb Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Tue, 15 Jul 2025 12:07:44 -0700 Subject: [PATCH 12/41] WIP: Add alert rules client dependency to callers in package policy service and tasks --- .../server/services/epm/package_service.ts | 15 +++++++++-- .../fleet/server/services/package_policy.ts | 16 +++++++++++- .../server/services/package_policy_service.ts | 4 ++- .../sync_integrations_on_remote.test.ts | 26 ++++++++++++++++++- .../sync_integrations_on_remote.ts | 6 ++++- .../sync_integrations_task.ts | 19 ++++++++++++-- 6 files changed, 78 insertions(+), 8 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts index 8023c6da7b768..7e3d29f78a3e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts @@ -15,7 +15,7 @@ import type { } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; - +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { TypeOf } from '@kbn/config-schema'; import { HTTPAuthorizationHeader } from '../../../common/http_authorization_header'; @@ -161,6 +161,7 @@ export class PackageServiceImpl implements PackageService { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, + private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger ) {} @@ -185,6 +186,7 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, + this.alertingRulesClient, this.logger, preflightCheck, request @@ -192,7 +194,12 @@ export class PackageServiceImpl implements PackageService { } public get asInternalUser() { - return new PackageClientImpl(this.internalEsClient, this.internalSoClient, this.logger); + return new PackageClientImpl( + this.internalEsClient, + this.internalSoClient, + this.alertingRulesClient, + this.logger + ); } } @@ -202,6 +209,7 @@ class PackageClientImpl implements PackageClient { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, + private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger, private readonly preflightCheck?: ( requiredAuthz?: FleetAuthzRouteConfig['fleetAuthz'] @@ -239,6 +247,7 @@ class PackageClientImpl implements PackageClient { ...options, esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, + alertingRulesClient: this.alertingRulesClient, }); } @@ -276,6 +285,7 @@ class PackageClientImpl implements PackageClient { installSource: 'registry', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, + alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, keepFailedInstallation, useStreaming, @@ -309,6 +319,7 @@ class PackageClientImpl implements PackageClient { installSource: 'custom', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, + alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, authorizationHeader: this.getAuthorizationHeader(), }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts index 58a878232158f..dd9b9e5cf4f6e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts @@ -23,6 +23,7 @@ import type { } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { SavedObjectsUtils } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { v4 as uuidv4 } from 'uuid'; import { load } from 'js-yaml'; import semverGt from 'semver/functions/gt'; @@ -235,6 +236,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { public async create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, packagePolicy: NewPackagePolicy, options: { authorizationHeader?: HTTPAuthorizationHeader | null; @@ -363,6 +365,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { if (!options?.skipEnsureInstalled) { await ensureInstalledPackage({ esClient, + alertingRulesClient, spaceId: options?.spaceId || DEFAULT_SPACE_ID, savedObjectsClient: soClient, pkgName: enrichedPackagePolicy.package.name, @@ -2148,6 +2151,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { public async buildPackagePolicyFromPackage( soClient: SavedObjectsClientContract, + alertingRulesClient: RulesClientApi, pkgName: string, options?: { logger?: Logger; installMissingPackage?: boolean } ): Promise { @@ -2161,6 +2165,7 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const esClient = await appContextService.getInternalUserESClient(); const result = await ensureInstalledPackage({ esClient, + alertingRulesClient, pkgName, savedObjectsClient: soClient, }); @@ -2648,6 +2653,7 @@ class PackagePolicyClientWithAuthz extends PackagePolicyClientImpl { async create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, packagePolicy: NewPackagePolicy, options?: { authorizationHeader?: HTTPAuthorizationHeader | null; @@ -2670,7 +2676,15 @@ class PackagePolicyClientWithAuthz extends PackagePolicyClientImpl { }, }); - return super.create(soClient, esClient, packagePolicy, options, context, request); + return super.create( + soClient, + esClient, + alertingRulesClient, + packagePolicy, + options, + context, + request + ); } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts index 4b150f4e415f8..1c31f409f7608 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts @@ -13,7 +13,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract, } from '@kbn/core/server'; - +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { SavedObjectError } from '@kbn/core-saved-objects-common'; import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header'; @@ -71,6 +71,7 @@ export interface PackagePolicyClient { create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClientApi: RulesClientApi, packagePolicy: NewPackagePolicy, options?: { spaceId?: string; @@ -205,6 +206,7 @@ export interface PackagePolicyClient { buildPackagePolicyFromPackage( soClient: SavedObjectsClientContract, + alertingRulesClientApi: RulesClientApi, pkgName: string, options?: { logger?: Logger; installMissingPackage?: boolean } ): Promise; diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts index 7fd5856dd1c0f..0e16f88101685 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts @@ -31,6 +31,7 @@ describe('syncIntegrationsOnRemote', () => { let packageClientMock: any; let loggerMock: any; let soClientMock: any; + let alertingRulesClientMock: any; beforeEach(() => { getIndicesMock = jest.fn(); @@ -63,6 +64,10 @@ describe('syncIntegrationsOnRemote', () => { soClientMock = { update: jest.fn(), }; + alertingRulesClientMock = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); it('should throw error if multiple synced integrations ccr indices exist', async () => { @@ -72,7 +77,14 @@ describe('syncIntegrationsOnRemote', () => { }); await expect( - syncIntegrationsOnRemote(esClientMock, soClientMock, {} as any, abortController, loggerMock) + syncIntegrationsOnRemote( + esClientMock, + soClientMock, + alertingRulesClientMock, + {} as any, + abortController, + loggerMock + ) ).rejects.toThrowError( 'Not supported to sync multiple indices with prefix fleet-synced-integrations-ccr-*' ); @@ -144,6 +156,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -172,6 +185,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -203,6 +217,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -245,6 +260,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -280,6 +296,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -312,6 +329,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -348,6 +366,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -372,6 +391,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -421,6 +441,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -466,6 +487,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -502,6 +524,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -538,6 +561,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 32b8efe1484e8..953b38f100468 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -10,6 +10,7 @@ import type { Logger, SavedObjectsClientContract, } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import semverEq from 'semver/functions/eq'; import semverGte from 'semver/functions/gte'; @@ -190,6 +191,7 @@ async function installPackageIfNotInstalled( async function uninstallPackageIfInstalled( esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClient, + alertingRulesClient: RulesClientApi, pkg: { package_name: string; package_version: string }, logger: Logger ) { @@ -213,6 +215,7 @@ async function uninstallPackageIfInstalled( try { await removeInstallation({ savedObjectsClient, + alertingRulesClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, esClient, @@ -231,6 +234,7 @@ async function uninstallPackageIfInstalled( export const syncIntegrationsOnRemote = async ( esClient: ElasticsearchClient, soClient: SavedObjectsClient, + alertingRulesClient: RulesClientApi, packageClient: PackageClient, abortController: AbortController, logger: Logger @@ -266,7 +270,7 @@ export const syncIntegrationsOnRemote = async ( if (abortController.signal.aborted) { throw new Error('Task was aborted'); } - await uninstallPackageIfInstalled(esClient, soClient, pkg, logger); + await uninstallPackageIfInstalled(esClient, soClient, alertingRulesClient, pkg, logger); } await clearCustomAssetFailedAttempts(soClient, syncIntegrationsDoc); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts index 4d15e1b1658d4..177557cc9e1da 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts @@ -7,14 +7,17 @@ import { keyBy } from 'lodash'; import { SavedObjectsClient } from '@kbn/core/server'; import type { CoreSetup, ElasticsearchClient, Logger } from '@kbn/core/server'; +import { kibanaRequestFactory } from '@kbn/core-http-server-utils'; import type { ConcreteTaskInstance, + RunContext, TaskManagerSetupContract, TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import { getDeleteTaskRunResult } from '@kbn/task-manager-plugin/server/task'; import type { LoggerFactory } from '@kbn/core/server'; import { errors } from '@elastic/elasticsearch'; +import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import { SO_SEARCH_LIMIT, outputType } from '../../../common/constants'; import type { NewRemoteElasticsearchOutput } from '../../../common/types'; @@ -68,7 +71,7 @@ export class SyncIntegrationsTask { [TYPE]: { title: TITLE, timeout: TIMEOUT, - createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { + createTaskRunner: ({ taskInstance }: RunContext) => { return { run: async () => { return this.runTask(taskInstance, core); @@ -135,9 +138,20 @@ export class SyncIntegrationsTask { return; } - const [coreStart, _startDeps, { packageService }] = (await core.getStartServices()) as any; + const fakeRequest = kibanaRequestFactory({ + headers: { authorization: `ApiKey ${taskInstance.apiKey}` }, + path: '/', + route: { settings: {} }, + url: { href: '', hash: '' } as URL, + raw: { req: { url: '/' } } as any, + }); + + core.http.basePath.set(fakeRequest, DEFAULT_SPACE_ID); + + const [coreStart, startDeps, { packageService }] = (await core.getStartServices()) as any; const esClient = coreStart.elasticsearch.client.asInternalUser; const soClient = new SavedObjectsClient(coreStart.savedObjects.createInternalRepository()); + const alertingRulesClient = startDeps.alerting.getRulesClientWithRequest(fakeRequest); try { // write integrations on main cluster @@ -147,6 +161,7 @@ export class SyncIntegrationsTask { await syncIntegrationsOnRemote( esClient, soClient, + alertingRulesClient, packageService.asInternalUser, this.abortController, this.logger From 06684cf473533ef6ea244ec8773ebc52c5eec4f0 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Wed, 16 Jul 2025 09:41:41 -0700 Subject: [PATCH 13/41] Revert providing alert rules client in sync integrations task --- .../tasks/sync_integrations/sync_integrations_on_remote.ts | 6 +----- .../tasks/sync_integrations/sync_integrations_task.ts | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 953b38f100468..32b8efe1484e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -10,7 +10,6 @@ import type { Logger, SavedObjectsClientContract, } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import semverEq from 'semver/functions/eq'; import semverGte from 'semver/functions/gte'; @@ -191,7 +190,6 @@ async function installPackageIfNotInstalled( async function uninstallPackageIfInstalled( esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClient, - alertingRulesClient: RulesClientApi, pkg: { package_name: string; package_version: string }, logger: Logger ) { @@ -215,7 +213,6 @@ async function uninstallPackageIfInstalled( try { await removeInstallation({ savedObjectsClient, - alertingRulesClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, esClient, @@ -234,7 +231,6 @@ async function uninstallPackageIfInstalled( export const syncIntegrationsOnRemote = async ( esClient: ElasticsearchClient, soClient: SavedObjectsClient, - alertingRulesClient: RulesClientApi, packageClient: PackageClient, abortController: AbortController, logger: Logger @@ -270,7 +266,7 @@ export const syncIntegrationsOnRemote = async ( if (abortController.signal.aborted) { throw new Error('Task was aborted'); } - await uninstallPackageIfInstalled(esClient, soClient, alertingRulesClient, pkg, logger); + await uninstallPackageIfInstalled(esClient, soClient, pkg, logger); } await clearCustomAssetFailedAttempts(soClient, syncIntegrationsDoc); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts index 177557cc9e1da..081b0fc121856 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts @@ -139,7 +139,7 @@ export class SyncIntegrationsTask { } const fakeRequest = kibanaRequestFactory({ - headers: { authorization: `ApiKey ${taskInstance.apiKey}` }, + headers: {}, path: '/', route: { settings: {} }, url: { href: '', hash: '' } as URL, From 122a4d4e04637ce29e1ef9c3ff6cd95ab2fc1d2d Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Wed, 16 Jul 2025 14:11:58 -0700 Subject: [PATCH 14/41] WIP: Have alertingRulesClient be optional for package install to support non-request contexts --- .../context/fixtures/integration.nginx.ts | 1 + .../context/fixtures/integration.okta.ts | 1 + .../shared/fleet/server/mocks/index.ts | 2 + .../plugins/shared/fleet/server/plugin.ts | 8 ++- .../fleet/server/routes/epm/index.test.ts | 1 + .../routes/epm/kibana_assets_handler.ts | 8 +++ .../routes/package_policy/handlers.test.ts | 2 +- .../server/routes/package_policy/handlers.ts | 5 ++ .../server/services/agent_policy.test.ts | 59 ++++++++++++------- .../fleet/server/services/agent_policy.ts | 48 +++++++++++---- .../services/agent_policy_create.test.ts | 27 +++++++-- .../server/services/agent_policy_create.ts | 46 ++++++++++----- .../epm/kibana/assets/install.test.ts | 6 +- .../services/epm/kibana/assets/install.ts | 28 +++++---- .../kibana/assets/install_with_streaming.ts | 12 +++- .../services/epm/package_service.test.ts | 12 +++- .../server/services/epm/package_service.ts | 27 ++++++--- .../packages/bulk_install_packages.test.ts | 7 +++ .../epm/packages/bulk_install_packages.ts | 4 ++ .../epm/packages/input_type_packages.test.ts | 11 ++++ .../epm/packages/input_type_packages.ts | 6 +- .../services/epm/packages/install.test.ts | 31 ++++++++++ .../server/services/epm/packages/install.ts | 14 ++--- .../_state_machine_package_install.test.ts | 10 ++++ .../_state_machine_package_install.ts | 2 +- .../step_create_restart_installation.test.ts | 9 +++ .../step_delete_previous_pipelines.test.ts | 14 +++++ .../steps/step_install_ilm_policies.test.ts | 14 +++++ ...p_install_index_template_pipelines.test.ts | 15 +++++ .../steps/step_install_kibana_assets.test.ts | 14 +++++ .../steps/step_install_mlmodel.test.ts | 12 ++++ .../steps/step_install_transforms.test.ts | 12 ++++ .../step_remove_legacy_templates.test.ts | 7 +++ .../steps/step_save_archive_entries.test.ts | 13 ++++ .../steps/step_save_system_object.test.ts | 7 +++ .../step_update_current_write_indices.test.ts | 8 +++ .../update_latest_executed_state.test.ts | 9 +++ .../services/epm/packages/reinstall.test.ts | 8 +++ .../server/services/epm/packages/reinstall.ts | 4 ++ .../server/services/epm/packages/remove.ts | 19 ++++-- .../update_custom_integration.test.ts | 55 +++++++++++++---- .../epm/packages/update_custom_integration.ts | 6 +- .../server/services/package_policy.test.ts | 10 ++++ .../server/services/package_policy_service.ts | 2 +- .../fleet/server/services/preconfiguration.ts | 8 ++- .../shared/fleet/server/services/setup.ts | 1 + .../sync_integrations_on_remote.test.ts | 26 +------- .../sync_integrations_on_remote.ts | 1 + 48 files changed, 513 insertions(+), 139 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts index ea89331156566..87d770d032074 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts @@ -80,6 +80,7 @@ export const item: GetInfoResponse['item'] = { // path: 'nginx-0.7.0/kibana/dashboard/nginx-55a9e6e0-a29e-11e7-928f-5dbe6f6f5519.json', }, ], + alert: [], ml_module: [ { pkgkey: 'nginx-0.7.0', diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts index ddae02803faf0..285857f81cd89 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts @@ -52,6 +52,7 @@ export const item: GetInfoResponse['item'] = { // path: 'okta-1.2.0/kibana/dashboard/okta-749203a0-67b1-11ea-a76f-bf44814e437d.json', }, ], + alert: [], map: [ { pkgkey: 'okta-1.2.0', diff --git a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts index 8bfccc605f3b5..a3318b10ad51e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts @@ -19,6 +19,7 @@ import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import { cloudMock } from '@kbn/cloud-plugin/public/mocks'; +import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { SPACES_EXTENSION_ID } from '@kbn/core-saved-objects-server'; import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; @@ -148,6 +149,7 @@ export const createAppContextStartContractMock = ( encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(), encryptedSavedObjectsSetup: encryptedSavedObjectsMock.createSetup({ canEncrypt: true }), savedObjects: mockedSavedObject, + alertingStart: alertsMock.createStart(), securityCoreStart: securityServiceMock.createStart(), securitySetup: securityMock.createSetup(), securityStart: securityMock.createStart(), diff --git a/x-pack/platform/plugins/shared/fleet/server/plugin.ts b/x-pack/platform/plugins/shared/fleet/server/plugin.ts index 4825753815761..bc16d3bf68791 100644 --- a/x-pack/platform/plugins/shared/fleet/server/plugin.ts +++ b/x-pack/platform/plugins/shared/fleet/server/plugin.ts @@ -51,7 +51,6 @@ import type { import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; - import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server'; import { KibanaFeatureScope } from '@kbn/features-plugin/common'; @@ -873,7 +872,8 @@ export class FleetPlugin fleetSetupCompleted: () => fleetSetupPromise, packageService: this.setupPackageService( core.elasticsearch.client.asInternalUser, - internalSoClient + internalSoClient, + plugins.alerting ), agentService: this.setupAgentService( core.elasticsearch.client.asInternalUser, @@ -937,7 +937,8 @@ export class FleetPlugin private setupPackageService( internalEsClient: ElasticsearchClient, - internalSoClient: SavedObjectsClientContract + internalSoClient: SavedObjectsClientContract, + alertingStart: AlertingServerStart ): PackageService { if (this.packageService) { return this.packageService; @@ -946,6 +947,7 @@ export class FleetPlugin this.packageService = new PackageServiceImpl( internalEsClient, internalSoClient, + alertingStart, this.getLogger() ); return this.packageService!; diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts index 96e25bfdc8c2a..c762bf182f15d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts @@ -190,6 +190,7 @@ describe('schema validation', () => { const assets: AssetsGroupedByServiceByType = { kibana: { dashboard: [], + alert: [], visualization: [], search: [], lens: [], diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts index 71de2f640a962..68fdbe5a7c8b8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts @@ -47,6 +47,9 @@ export const installPackageKibanaAssetsHandler: FleetRequestHandler< > = async (context, request, response) => { const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const logger = appContextService.getLogger(); const spaceId = fleetContext.spaceId; const { pkgName, pkgVersion } = request.params; @@ -81,6 +84,7 @@ export const installPackageKibanaAssetsHandler: FleetRequestHandler< for (const spaceToInstallId of spaceIds) { await installKibanaAssetsAndReferences({ savedObjectsClient: appContextService.getInternalUserSOClientForSpaceId(spaceToInstallId), + alertingRulesClient, logger, pkgName, pkgTitle: packageInfo.title, @@ -105,6 +109,9 @@ export const deletePackageKibanaAssetsHandler: FleetRequestHandler< > = async (context, request, response) => { const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const logger = appContextService.getLogger(); const spaceId = fleetContext.spaceId; const { pkgName, pkgVersion } = request.params; @@ -120,6 +127,7 @@ export const deletePackageKibanaAssetsHandler: FleetRequestHandler< await deleteKibanaAssetsAndReferencesForSpace({ savedObjectsClient, + alertingRulesClient, logger, pkgName, spaceId, diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts index e8904d82a7632..a4d15ccf407e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts @@ -92,7 +92,7 @@ jest.mock( ), buildPackagePolicyFromPackage: jest.fn(), bulkCreate: jest.fn(), - create: jest.fn((soClient, esClient, newData) => + create: jest.fn((soClient, esClient, alertingRulesClient, newData) => Promise.resolve({ ...newData, inputs: newData.inputs.map((input) => ({ diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts index 117ff3c219631..5e16f9e1887a5 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts @@ -226,6 +226,9 @@ export const createPackagePolicyHandler: FleetRequestHandler< const fleetContext = await context.fleet; const soClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; + const alertingRulesClient = await appContextService + .getAlerting() + .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; const { force, id, package: pkg, ...newPolicy } = request.body; if ('spaceIds' in newPolicy) { @@ -270,6 +273,7 @@ export const createPackagePolicyHandler: FleetRequestHandler< const packagePolicy = await fleetContext.packagePolicyService.asCurrentUser.create( soClient, esClient, + alertingRulesClient, newPackagePolicy, { id, @@ -304,6 +308,7 @@ export const createPackagePolicyHandler: FleetRequestHandler< .info(`rollback ${pkg!.name}-${pkg!.version} package installation after error`); await removeInstallation({ savedObjectsClient: soClient, + alertingRulesClient, pkgName: pkg!.name, pkgVersion: pkg!.version, esClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts index 8ca7af0a29edc..844faa3c21a3c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts @@ -162,6 +162,11 @@ function getAgentPolicyCreateMock() { } let mockedLogger: jest.Mocked; +const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), +} as any; + describe('Agent policy', () => { beforeEach(() => { mockedLogger = loggerMock.create(); @@ -923,7 +928,7 @@ describe('Agent policy', () => { soClient ); mockedAppContextService.getInternalUserSOClientForSpaceId.mockReturnValue(soClient); - await agentPolicyService.removeOutputFromAll(esClient, 'output-id-123'); + await agentPolicyService.removeOutputFromAll(esClient, alertingRulesClient, 'output-id-123'); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledTimes(2); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledWith( @@ -984,7 +989,11 @@ describe('Agent policy', () => { ], } as any); - await agentPolicyService.removeDefaultSourceFromAll(esClient, 'default-download-source-id'); + await agentPolicyService.removeDefaultSourceFromAll( + esClient, + alertingRulesClient, + 'default-download-source-id' + ); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledTimes(2); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledWith( @@ -1035,7 +1044,7 @@ describe('Agent policy', () => { }, ], }); - await agentPolicyService.update(soClient, esClient, 'mocked', { + await agentPolicyService.update(soClient, esClient, alertingRulesClient, 'mocked', { name: 'mocked', namespace: 'default', is_managed: false, @@ -1044,7 +1053,7 @@ describe('Agent policy', () => { let calledWith = soClient.update.mock.calls[0]; expect(calledWith[2]).toHaveProperty('is_managed', false); - await agentPolicyService.update(soClient, esClient, 'mocked', { + await agentPolicyService.update(soClient, esClient, alertingRulesClient, 'mocked', { name: 'is_managed: true provided', namespace: 'default', is_managed: true, @@ -1071,7 +1080,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { is_protected: true, }) ).rejects.toThrowError( @@ -1096,11 +1105,17 @@ describe('Agent policy', () => { ], }); - await agentPolicyService.update(soClient, esClient, 'test-agent-policy', { - name: 'Test Agent Policy', - namespace: 'default', - is_managed: false, - }); + await agentPolicyService.update( + soClient, + esClient, + alertingRulesClient, + 'test-agent-policy', + { + name: 'Test Agent Policy', + namespace: 'default', + is_managed: false, + } + ); expect(mockedAuditLoggingService.writeCustomSoAuditLog).toHaveBeenCalledWith({ action: 'update', @@ -1128,7 +1143,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', is_protected: true, @@ -1156,7 +1171,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', }) @@ -1189,7 +1204,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', is_protected: true, @@ -1219,7 +1234,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1249,7 +1264,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1280,7 +1295,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1311,7 +1326,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, 'test-id', { + agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { name: 'test', namespace: 'default', }) @@ -1342,7 +1357,7 @@ describe('Agent policy', () => { }, ] as any); try { - await agentPolicyService.copy(soClient, esClient, 'mocked', { + await agentPolicyService.copy(soClient, esClient, alertingRulesClient, 'mocked', { name: 'copy mocked', }); } catch (e) { @@ -1421,7 +1436,7 @@ describe('Agent policy', () => { ] as any; mockedPackagePolicyService.findAllForAgentPolicy.mockReturnValue(packagePolicies); mockedPackagePolicyService.list.mockResolvedValue({ items: packagePolicies } as any); - await agentPolicyService.copy(soClient, esClient, 'mocked', { + await agentPolicyService.copy(soClient, esClient, alertingRulesClient, 'mocked', { name: 'copy mocked', }); expect(mockedPackagePolicyService.bulkCreate).toBeCalledWith( @@ -1494,7 +1509,7 @@ describe('Agent policy', () => { soClient.bulkGet.mockResolvedValue({ saved_objects: [mockSo], }); - await agentPolicyService.deployPolicy(soClient, 'policy123'); + await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'policy123'); expect(esClient.create).not.toBeCalled(); }); @@ -1546,7 +1561,7 @@ describe('Agent policy', () => { soClient.bulkGet.mockResolvedValue({ saved_objects: [mockSo], }); - await agentPolicyService.deployPolicy(soClient, 'policy123'); + await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'policy123'); expect(esClient.bulk).toBeCalledWith( expect.objectContaining({ @@ -1594,7 +1609,7 @@ describe('Agent policy', () => { ], }); - await agentPolicyService.deployPolicy(soClient, 'test-agent-policy'); + await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'test-agent-policy'); expect(mockedAuditLoggingService.writeCustomAuditLog).toHaveBeenCalledWith({ message: `User deploying policy [id=test-agent-policy]`, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts index 2473db96d9073..eb4d1c9cc661e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts @@ -23,13 +23,10 @@ import type { } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { SavedObjectsUtils } from '@kbn/core/server'; - import type { BulkResponseItem } from '@elastic/elasticsearch/lib/api/types'; - import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; - +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { SavedObjectError } from '@kbn/core-saved-objects-common'; - import { withSpan } from '@kbn/apm-utils'; import { catchAndSetErrorStackTrace } from '../errors/utils'; @@ -825,6 +822,7 @@ class AgentPolicyService { public async update( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi | null, id: string, agentPolicy: Partial, options?: { @@ -898,6 +896,7 @@ class AgentPolicyService { await bulkInstallPackages({ savedObjectsClient: soClient, esClient, + alertingRulesClient, packagesToInstall, spaceId: options?.spaceId || DEFAULT_SPACE_ID, authorizationHeader: options?.authorizationHeader, @@ -925,6 +924,7 @@ class AgentPolicyService { public async copy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, id: string, newAgentPolicyProps: Pick, options?: { user?: AuthenticatedUser } @@ -1044,7 +1044,7 @@ class AgentPolicyService { user: options?.user, }); } else { - await this.deployPolicy(soClient, newAgentPolicy.id); + await this.deployPolicy(soClient, alertingRulesClient, newAgentPolicy.id); } // Get updated agent policy with package policies and adjusted tamper protection @@ -1086,6 +1086,7 @@ class AgentPolicyService { */ public async removeOutputFromAll( esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, outputId: string, options?: { force?: boolean } ) { @@ -1139,10 +1140,17 @@ class AgentPolicyService { const soClient = appContextService.getInternalUserSOClientForSpaceId( agentPolicy.space_ids?.[0] ); - return this.update(soClient, esClient, agentPolicy.id, getAgentPolicy(agentPolicy), { - skipValidation: true, - force: options?.force, - }); + return this.update( + soClient, + esClient, + alertingRulesClient, + agentPolicy.id, + getAgentPolicy(agentPolicy), + { + skipValidation: true, + force: options?.force, + } + ); }, { concurrency: MAX_CONCURRENT_AGENT_POLICIES_OPERATIONS, @@ -1156,6 +1164,7 @@ class AgentPolicyService { */ public async removeFleetServerHostFromAll( esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, fleetServerHostId: string, options?: { force?: boolean } ) { @@ -1180,6 +1189,7 @@ class AgentPolicyService { this.update( appContextService.getInternalUserSOClientForSpaceId(agentPolicy.space_ids?.[0]), esClient, + alertingRulesClient, agentPolicy.id, { fleet_server_host_id: null, @@ -1489,14 +1499,21 @@ class AgentPolicyService { public async deployPolicy( soClient: SavedObjectsClientContract, + alertingRulesClient: RulesClientApi, agentPolicyId: string, agentPolicy?: AgentPolicy | null ) { - await this.deployPolicies(soClient, [agentPolicyId], agentPolicy ? [agentPolicy] : undefined); + await this.deployPolicies( + soClient, + alertingRulesClient, + [agentPolicyId], + agentPolicy ? [agentPolicy] : undefined + ); } public async deployPolicies( soClient: SavedObjectsClientContract, + alertingRulesClient: RulesClientApi, agentPolicyIds: string[], agentPolicies?: AgentPolicy[] ) { @@ -1640,6 +1657,7 @@ class AgentPolicyService { return agentPolicyService.update( soClient, esClient, + alertingRulesClient, fleetServerPolicy.policy_id, { schema_version: FLEET_AGENT_POLICIES_SCHEMA_VERSION, @@ -1762,7 +1780,11 @@ class AgentPolicyService { * @param esClient * @param downloadSourceId */ - public async removeDefaultSourceFromAll(esClient: ElasticsearchClient, downloadSourceId: string) { + public async removeDefaultSourceFromAll( + esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, + downloadSourceId: string + ) { const savedObjectType = await getAgentPolicySavedObjectType(); const agentPolicies = ( await appContextService @@ -1784,6 +1806,7 @@ class AgentPolicyService { this.update( appContextService.getInternalUserSOClientForSpaceId(agentPolicy.space_ids?.[0]), esClient, + alertingRulesClient, agentPolicy.id, { download_source_id: @@ -2185,6 +2208,7 @@ export const agentPolicyService = new AgentPolicyService(); export async function addPackageToAgentPolicy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi | null, agentPolicy: AgentPolicy, packageInfo: PackageInfo, packagePolicyName?: string, @@ -2211,7 +2235,7 @@ export async function addPackageToAgentPolicy( ? String(packagePolicyId) : uuidv5(`${agentPolicy.id}-${packagePolicyName}`, UUID_V5_NAMESPACE); - await packagePolicyService.create(soClient, esClient, newPackagePolicy, { + await packagePolicyService.create(soClient, esClient, alertingRulesClient, newPackagePolicy, { id, bumpRevision: bumpAgentPolicyRevison, skipEnsureInstalled: true, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts index aa85bbbf6c56d..709e3df016439 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts @@ -60,6 +60,10 @@ function getPackagePolicy(name: string, policyId = '') { describe('createAgentPolicyWithPackages', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const soClientMock = savedObjectsClientMock.create(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; beforeEach(() => { appContextService.start(createAppContextStartContractMock()); @@ -74,15 +78,17 @@ describe('createAgentPolicyWithPackages', () => { mockedAgentPolicyService.deployPolicy.mockResolvedValue(); mockedPackagePolicyService.buildPackagePolicyFromPackage.mockImplementation( - (soClient, packageToInstall) => Promise.resolve(getPackagePolicy(packageToInstall)) + (soClient, _alertingRulesClient, packageToInstall) => + Promise.resolve(getPackagePolicy(packageToInstall)) ); mockIncrementPackageName.mockImplementation((soClient: any, pkg: string) => Promise.resolve(`${pkg}-1`) ); - mockedPackagePolicyService.create.mockImplementation((soClient, esClient, newPolicy) => - Promise.resolve({ - ...newPolicy, - } as PackagePolicy) + mockedPackagePolicyService.create.mockImplementation( + (soClient, esClient, _alertingRulesClient, newPolicy) => + Promise.resolve({ + ...newPolicy, + } as PackagePolicy) ); }); @@ -99,6 +105,7 @@ describe('createAgentPolicyWithPackages', () => { await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -121,6 +128,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Fleet Server policy', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: true, @@ -154,6 +162,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Fleet Server policy 2', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: false, @@ -179,6 +188,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -204,7 +214,7 @@ describe('createAgentPolicyWithPackages', () => { mockedAgentPolicyService.create.mockImplementation( async (soClient, esClient, newPolicy, options) => { if (!options?.skipDeploy) { - await mockedAgentPolicyService.deployPolicy(soClientMock, 'new_id'); + await mockedAgentPolicyService.deployPolicy(soClientMock, alertingRulesClient, 'new_id'); } return Promise.resolve({ ...newPolicy, @@ -215,6 +225,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -234,6 +245,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -259,6 +271,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -272,6 +285,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -291,6 +305,7 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, + alertingRulesClient, newPolicy: { id: 'new_fleet_server_policy', name: 'Fleet Server policy', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts index 07f93852356ae..65a5e707edfb7 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts @@ -10,6 +10,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract, } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { getDefaultFleetServerpolicyId } from '../../common/services/agent_policies_helpers'; import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header'; @@ -65,6 +66,7 @@ async function getFleetServerAgentPolicyId( async function createPackagePolicy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, agentPolicy: AgentPolicy, packageToInstall: string, options: { @@ -75,7 +77,7 @@ async function createPackagePolicy( } ) { const newPackagePolicy = await packagePolicyService - .buildPackagePolicyFromPackage(soClient, packageToInstall) + .buildPackagePolicyFromPackage(soClient, alertingRulesClient, packageToInstall) .catch(async (error) => { // rollback agent policy on error await agentPolicyService.delete(soClient, esClient, agentPolicy.id, { @@ -94,7 +96,7 @@ async function createPackagePolicy( newPackagePolicy.supports_agentless = agentPolicy.supports_agentless; } - await packagePolicyService.create(soClient, esClient, newPackagePolicy, { + await packagePolicyService.create(soClient, esClient, alertingRulesClient, newPackagePolicy, { spaceId: options.spaceId, user: options.user, bumpRevision: false, @@ -106,6 +108,7 @@ async function createPackagePolicy( interface CreateAgentPolicyParams { soClient: SavedObjectsClientContract; esClient: ElasticsearchClient; + alertingRulesClient: RulesClientApi; newPolicy: NewAgentPolicy; hasFleetServer?: boolean; withSysMonitoring: boolean; @@ -119,6 +122,7 @@ interface CreateAgentPolicyParams { export async function createAgentPolicyWithPackages({ soClient, esClient, + alertingRulesClient, newPolicy, hasFleetServer, withSysMonitoring, @@ -179,22 +183,36 @@ export async function createAgentPolicyWithPackages({ // Create the fleet server package policy and add it to agent policy. if (hasFleetServer) { - await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SERVER_PACKAGE, { - spaceId, - user, - authorizationHeader, - force, - }); + await createPackagePolicy( + soClient, + esClient, + alertingRulesClient, + agentPolicy, + FLEET_SERVER_PACKAGE, + { + spaceId, + user, + authorizationHeader, + force, + } + ); } // Create the system monitoring package policy and add it to agent policy. if (withSysMonitoring) { - await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SYSTEM_PACKAGE, { - spaceId, - user, - authorizationHeader, - force, - }); + await createPackagePolicy( + soClient, + esClient, + alertingRulesClient, + agentPolicy, + FLEET_SYSTEM_PACKAGE, + { + spaceId, + user, + authorizationHeader, + force, + } + ); } await ensureDefaultEnrollmentAPIKeyForAgentPolicy(soClient, esClient, agentPolicy.id); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts index 3b200ac5115cf..ce9b484005013 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts @@ -12,7 +12,7 @@ import type { } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; -import { type ArchiveAsset } from './install'; +import type { SavedObjectAsset, ArchiveAsset } from './install'; jest.mock('timers/promises', () => ({ async setTimeout() {}, @@ -31,8 +31,8 @@ const createImportError = (so: ArchiveAsset, type: string) => ({ id: so.id, error: { type } } as SavedObjectsImportFailure); const createImportSuccess = (so: ArchiveAsset) => ({ id: so.id, type: so.type, meta: {} } as SavedObjectsImportSuccess); -const createAsset = (asset: Partial) => - ({ id: 1234, type: 'dashboard', attributes: {}, ...asset } as ArchiveAsset); +const createAsset = (asset: Partial) => + ({ id: 1234, type: 'dashboard', attributes: {}, ...asset } as SavedObjectAsset); const createImportResponse = ( errors: SavedObjectsImportFailure[] = [], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 1b0b5d2377304..fe6b6584eec96 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -138,7 +138,7 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; logger: Logger; pkgName: string; spaceId: string; @@ -172,13 +172,21 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - const installedAlertRules = await installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets: asAlertRules, - assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, - context: { pkgName, spaceId, assetTags }, - }); + let installedAlertRules: ObjectReference[] = []; + + if (alertingRulesClient) { + installedAlertRules = await installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets: asAlertRules, + assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, + context: { pkgName, spaceId, assetTags }, + }); + } else if (asAlertRules.length) { + logger.debug( + `Installing ${asAlertRules.length} alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.` + ); + } const installedAssets = await installKibanaSavedObjects({ logger, @@ -251,7 +259,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; logger: Logger; pkgName: string; pkgTitle: string; @@ -322,7 +330,7 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; logger: Logger; pkgName: string; pkgTitle: string; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index f24e2107a022a..27fd8bf1b66db 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -32,7 +32,7 @@ interface InstallKibanaAssetsWithStreamingArgs { packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; @@ -89,7 +89,7 @@ export async function installKibanaAssetsWithStreaming({ } }); - if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS) { + if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS && alertingRulesClient) { await installAlertRules({ logger, alertingRulesClient, @@ -110,7 +110,13 @@ export async function installKibanaAssetsWithStreaming({ }); } - if (alertRuleBatch.length) { + if (alertRuleBatch.length && !alertingRulesClient) { + logger.debug( + `Installing ${alertRuleBatch.length} alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.` + ); + } + + if (alertRuleBatch.length && alertingRulesClient) { await installAlertRules({ logger, alertingRulesClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts index ea7586b9ebd78..75d14c15cb3e3 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts @@ -21,6 +21,7 @@ import { loggingSystemMock, savedObjectsClientMock, } from '@kbn/core/server/mocks'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { FleetUnauthorizedError } from '../../errors'; import type { InstallablePackage } from '../../types'; @@ -237,13 +238,22 @@ describe('PackageService', () => { let mockPackageService: PackageService; let mockEsClient: ElasticsearchClient; let mockSoClient: SavedObjectsClientContract; + let mockAlertingStart: AlertingServerStart; let mockLogger: MockedLogger; beforeEach(() => { mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); mockSoClient = savedObjectsClientMock.create(); mockLogger = loggingSystemMock.createLogger(); - mockPackageService = new PackageServiceImpl(mockEsClient, mockSoClient, mockLogger); + mockAlertingStart = { + getRulesClientWithRequest: jest.fn(), + } as any; + mockPackageService = new PackageServiceImpl( + mockEsClient, + mockSoClient, + mockAlertingStart, + mockLogger + ); }); afterEach(() => { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts index 7e3d29f78a3e8..8c2aa8409ce21 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts @@ -15,8 +15,8 @@ import type { } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { TypeOf } from '@kbn/config-schema'; +import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { HTTPAuthorizationHeader } from '../../../common/http_authorization_header'; @@ -161,7 +161,7 @@ export class PackageServiceImpl implements PackageService { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingRulesClient: RulesClientApi, + private readonly alertingStart: AlertingServerStart, private readonly logger: Logger ) {} @@ -186,7 +186,7 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, - this.alertingRulesClient, + this.alertingStart, this.logger, preflightCheck, request @@ -197,7 +197,7 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, - this.alertingRulesClient, + this.alertingStart, this.logger ); } @@ -209,7 +209,7 @@ class PackageClientImpl implements PackageClient { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingRulesClient: RulesClientApi, + private readonly alertingStart: AlertingServerStart, private readonly logger: Logger, private readonly preflightCheck?: ( requiredAuthz?: FleetAuthzRouteConfig['fleetAuthz'] @@ -242,12 +242,15 @@ class PackageClientImpl implements PackageClient { force?: boolean; }): Promise { await this.#runPreflight(INSTALL_PACKAGES_AUTHZ); + const alertingRulesClient = this.request + ? await this.alertingStart.getRulesClientWithRequest(this.request) + : null; return ensureInstalledPackage({ ...options, esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, + alertingRulesClient, }); } @@ -278,6 +281,10 @@ class PackageClientImpl implements PackageClient { : await Registry.fetchFindLatestPackageOrThrow(pkgName, { prerelease: true }); const pkgkey = Registry.pkgToPkgKey(pkgKeyProps); + const alertingRulesClient = this.request + ? await this.alertingStart.getRulesClientWithRequest(this.request) + : null; + return await installPackage({ force, pkgkey, @@ -285,7 +292,7 @@ class PackageClientImpl implements PackageClient { installSource: 'registry', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, + alertingRulesClient, neverIgnoreVerificationError: !force, keepFailedInstallation, useStreaming, @@ -310,6 +317,10 @@ class PackageClientImpl implements PackageClient { force = false, } = options; + const alertingRulesClient = this.request + ? await this.alertingStart.getRulesClientWithRequest(this.request) + : null; + return await installPackage({ force, pkgName, @@ -319,7 +330,7 @@ class PackageClientImpl implements PackageClient { installSource: 'custom', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, + alertingRulesClient, neverIgnoreVerificationError: !force, authorizationHeader: this.getAuthorizationHeader(), }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts index 17958699365e6..3205fd015bd9d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts @@ -28,6 +28,10 @@ describe('bulkInstallPackages', () => { let mockContract: ReturnType; const mockSoClient = savedObjectsClientMock.create(); const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; beforeEach(() => { mockContract = createAppContextStartContractMock(); @@ -42,6 +46,7 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, + alertingRulesClient, packagesToInstall, esClient: mockEsClient, spaceId: 'default', @@ -60,6 +65,7 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, + alertingRulesClient, packagesToInstall, esClient: mockEsClient, spaceId: 'default', @@ -78,6 +84,7 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, + alertingRulesClient, packagesToInstall: [...stringPackagesToInstall, ...objectPackagesToInstall], esClient: mockEsClient, spaceId: 'default', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts index dd155da3e6b74..9673a17e39194 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts @@ -6,6 +6,7 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import pLimit from 'p-limit'; import { uniqBy } from 'lodash'; @@ -22,6 +23,7 @@ import type { BulkInstallResponse, IBulkInstallPackageError } from './install'; interface BulkInstallPackagesParams { savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi | null; packagesToInstall: Array< | string | { name: string; version?: string; prerelease?: boolean; skipDataStreamRollover?: boolean } @@ -37,6 +39,7 @@ interface BulkInstallPackagesParams { export async function bulkInstallPackages({ savedObjectsClient, + alertingRulesClient, packagesToInstall, esClient, spaceId, @@ -139,6 +142,7 @@ export async function bulkInstallPackages({ const installResult = await installPackage({ savedObjectsClient, esClient, + alertingRulesClient, pkgkey, installSource: 'registry', spaceId, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts index a060e902140e9..3aa5b10c12304 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts @@ -54,6 +54,11 @@ jest.mock('../../app_context', () => { }; }); +const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), +} as any; + describe('installAssetsForInputPackagePolicy', () => { beforeEach(() => { jest.mocked(optimisticallyAddEsAssetReferences).mockReset(); @@ -172,6 +177,7 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -187,6 +193,7 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -233,6 +240,7 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).toBeCalledWith( @@ -291,6 +299,7 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).toBeCalledWith( @@ -326,6 +335,7 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -349,6 +359,7 @@ describe('removeAssetsForInputPackagePolicy', () => { } as any, datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), + alertingRulesClient, esClient: {} as ElasticsearchClient, logger: mockedLogger, }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts index c1adc75e7d10b..728c570b56df4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts @@ -6,6 +6,7 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract, Logger } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { IndicesDataStream } from 'elasticsearch-8.x/lib/api/types'; @@ -214,8 +215,10 @@ export async function removeAssetsForInputPackagePolicy(opts: { logger: Logger; esClient: ElasticsearchClient; savedObjectsClient: SavedObjectsClientContract; + alertingRulesClient: RulesClientApi; }) { - const { logger, packageInfo, esClient, savedObjectsClient, datasetName } = opts; + const { logger, packageInfo, esClient, savedObjectsClient, alertingRulesClient, datasetName } = + opts; if (packageInfo.type === 'input' && packageInfo.status === 'installed') { logger.info(`Removing assets for input package ${packageInfo.name}:${packageInfo.version}`); @@ -257,6 +260,7 @@ export async function removeAssetsForInputPackagePolicy(opts: { installationToDelete, installation, esClient, + alertingRulesClient, savedObjectsClient ); } catch (error) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts index 146c1712b6513..ec75d92f947df 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts @@ -163,6 +163,10 @@ describe('createInstallation', () => { }); describe('install', () => { + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; beforeEach(() => { jest .mocked(Registry.fetchFindLatestPackageOrThrow) @@ -191,6 +195,7 @@ describe('install', () => { pkgkey: 'apache-1.1.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -214,6 +219,7 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -237,6 +243,7 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -263,6 +270,7 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -289,6 +297,7 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -319,6 +328,7 @@ describe('install', () => { pkgkey: 'test_package-1.0.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.error).toBeUndefined(); @@ -336,6 +346,7 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.status).toEqual('installed'); @@ -365,6 +376,7 @@ describe('install', () => { pkgkey: 'apache-1.2.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.status).toEqual('already_installed'); @@ -389,6 +401,7 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.error).toBeDefined(); expect(response.error!.message).toEqual( @@ -407,6 +420,7 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, force: true, }); expect(response.error).toBeUndefined(); @@ -423,6 +437,7 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.error).toBeUndefined(); }); @@ -443,6 +458,7 @@ describe('install', () => { pkgkey: 'fleet_server-2.0.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.status).toEqual('installed'); @@ -457,6 +473,7 @@ describe('install', () => { pkgkey: 'security_detection_engine', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(response.error).toBeUndefined(); @@ -480,6 +497,7 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -502,6 +520,7 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -528,6 +547,7 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, + alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -548,6 +568,10 @@ describe('install', () => { describe('handleInstallPackageFailure', () => { const mockedLogger = jest.mocked(appContextService.getLogger()); const savedObjectsClient = savedObjectsClientMock.create(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; beforeEach(() => { mockedLogger.error.mockClear(); @@ -598,6 +622,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new ConcurrentInstallOperationError('test 123'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -629,6 +654,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new FleetError('test 123'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -676,6 +702,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test 123'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -712,6 +739,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test 123'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg: undefined as any, pkgName, pkgVersion: '1.0.0', @@ -752,6 +780,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -814,6 +843,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -876,6 +906,7 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, + alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index d96aed266e310..b2c667ab24a9d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -175,7 +175,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -285,7 +285,7 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -408,7 +408,7 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -432,7 +432,7 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -441,7 +441,7 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -625,7 +625,7 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -1341,7 +1341,7 @@ export const saveKibanaAssetsRefs = async ( export async function ensurePackagesCompletedInstall( savedObjectsClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi + alertingRulesClient: RulesClientApi | null ) { const installingPackages = await getPackageSavedObjects(savedObjectsClient, { searchFields: ['install_status'], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts index dfd6cce6b91bc..d90587c809bfa 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts @@ -67,6 +67,7 @@ function sleep(millis: number) { describe('_stateMachineInstallPackage', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; beforeEach(async () => { soClient = savedObjectsClientMock.create(); @@ -82,6 +83,10 @@ describe('_stateMachineInstallPackage', () => { jest.mocked(saveArchiveEntriesFromAssetsMap).mockResolvedValue({ saved_objects: [], }); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(() => { @@ -109,6 +114,7 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -171,6 +177,7 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -207,6 +214,7 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -256,6 +264,7 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -323,6 +332,7 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { packageInfo: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts index bc4c72cdf38ca..375f220e8e066 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts @@ -62,7 +62,7 @@ import { handleState } from './state_machine'; export interface InstallContext extends StateContext { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; esClient: ElasticsearchClient; logger: Logger; installedPkg?: SavedObject; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts index 6cec95cd7c53c..d3bc4dce9d22c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts @@ -46,6 +46,7 @@ const mockedAuditLoggingService = auditLoggingService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); describe('When package is stuck in `installing`', () => { @@ -71,6 +72,10 @@ describe('stepCreateRestartInstallation', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(() => { mockedAuditLoggingService.writeCustomSoAuditLog.mockReset(); @@ -83,6 +88,7 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -119,6 +125,7 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -163,6 +170,7 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -207,6 +215,7 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts index 06201770ee2e2..2e1e3e7054a75 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts @@ -40,6 +40,8 @@ const mockedIsTopLevelPipeline = isTopLevelPipeline as jest.MockedFunction< describe('stepDeletePreviousPipelines', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; + const getMockInstalledPackageSo = ( installedEs: EsAssetReference[] = [] ): SavedObject => { @@ -65,6 +67,10 @@ describe('stepDeletePreviousPipelines', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedDeletePreviousPipelines).mockReset(); @@ -131,6 +137,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -177,6 +184,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -223,6 +231,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -316,6 +325,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'update', @@ -346,6 +356,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'reupdate', @@ -376,6 +387,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'rollback', @@ -416,6 +428,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { ...packageInstallContext, paths: ['some/path/1', 'some/path/2'] }, installType: 'install', @@ -457,6 +470,7 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { ...packageInstallContext, paths: ['some/path/1', 'some/path/2'] }, installType: 'update', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts index 7b78b7967abc7..b03b41ea01dd1 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts @@ -63,6 +63,7 @@ const packageInstallContext = { }; let soClient: jest.Mocked; let esClient: jest.Mocked; +let alertingRulesClient: any; describe('stepInstallILMPolicies', () => { const mockInstalledPackageSo: SavedObject = { @@ -95,6 +96,10 @@ describe('stepInstallILMPolicies', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(installILMPolicy).mockReset(); @@ -122,6 +127,7 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -154,6 +160,7 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -227,6 +234,7 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { packageInfo: { @@ -322,6 +330,7 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -447,6 +456,7 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -505,6 +515,7 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -533,6 +544,7 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -559,6 +571,7 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -586,6 +599,7 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts index 1c368cfd998d3..e534fb0d64bdc 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts @@ -49,6 +49,7 @@ const mockedInstallIndexTemplatesAndPipelines = >; let soClient: jest.Mocked; let esClient: jest.Mocked; +let alertingRulesClient: any; describe('stepInstallIndexTemplatePipelines', () => { const getMockInstalledPackageSo = ( @@ -76,6 +77,10 @@ describe('stepInstallIndexTemplatePipelines', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedInstallIndexTemplatesAndPipelines).mockReset(); @@ -160,6 +165,7 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -324,6 +330,7 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -471,6 +478,7 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -550,6 +558,7 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -604,6 +613,7 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -714,6 +724,7 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -772,6 +783,7 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -800,6 +812,7 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -826,6 +839,7 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -853,6 +867,7 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts index 873fa86e5df74..31054f4e6c96c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts @@ -59,6 +59,7 @@ const mockedDeleteKibanaAssets = deleteKibanaAssets as jest.MockedFunction< let soClient: jest.Mocked; let esClient: jest.Mocked; +let alertingRulesClient: any; const packageInstallContext = { packageInfo: { @@ -87,6 +88,10 @@ describe('stepInstallKibanaAssets', () => { soClient.get.mockImplementation(async (type, id) => { return { id, attributes: {} } as any; }); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; @@ -96,6 +101,7 @@ describe('stepInstallKibanaAssets', () => { const installationPromise = stepInstallKibanaAssets({ savedObjectsClient: soClient, esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -135,6 +141,7 @@ describe('stepInstallKibanaAssets', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -181,6 +188,7 @@ describe('stepInstallKibanaAssetsWithStreaming', () => { const result = await stepInstallKibanaAssetsWithStreaming({ savedObjectsClient: soClient, esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator, @@ -249,6 +257,7 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -280,6 +289,7 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -307,6 +317,7 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -332,6 +343,7 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -358,6 +370,7 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -397,6 +410,7 @@ describe('cleanUpUnusedKibanaAssetsStep', () => { savedObjectsClient: soClient, savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install' as const, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts index df939f3a458b6..389a5d3a566bc 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts @@ -59,6 +59,7 @@ const packageInstallContext = { }; let soClient: jest.Mocked; let esClient: jest.Mocked; +let alertingRulesClient: any; describe('stepInstallMlModel', () => { const getMockInstalledPackageSo = ( @@ -86,6 +87,10 @@ describe('stepInstallMlModel', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedInstallMlModel).mockReset(); @@ -122,6 +127,7 @@ describe('stepInstallMlModel', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -151,6 +157,7 @@ describe('stepInstallMlModel', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -227,6 +234,7 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -285,6 +293,7 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -313,6 +322,7 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -339,6 +349,7 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -366,6 +377,7 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts index 3bf07d52c6cbf..c561dc919a379 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts @@ -38,6 +38,7 @@ const mockCleanupTransforms = cleanupTransforms as jest.MockedFunction; let esClient: jest.Mocked; +let alertingRulesClient: any; const packageInstallContext = { packageInfo: { @@ -83,6 +84,10 @@ describe('stepInstallTransforms', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedInstallTransforms).mockReset(); @@ -122,6 +127,7 @@ describe('stepInstallTransforms', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -154,6 +160,7 @@ describe('stepInstallTransforms', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -229,6 +236,7 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -255,6 +263,7 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -282,6 +291,7 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -307,6 +317,7 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -333,6 +344,7 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts index 7fa00a1c57f57..2734f3a606170 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts @@ -37,6 +37,7 @@ const mockedRemoveLegacyTemplates = removeLegacyTemplates as jest.MockedFunction describe('stepRemoveLegacyTemplates', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); const getMockInstalledPackageSo = ( @@ -64,6 +65,10 @@ describe('stepRemoveLegacyTemplates', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedRemoveLegacyTemplates).mockReset(); @@ -116,6 +121,7 @@ describe('stepRemoveLegacyTemplates', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext, installedPkg, @@ -139,6 +145,7 @@ describe('stepRemoveLegacyTemplates', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext, installedPkg, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts index 26a4f17132357..7ee954cc5e9fb 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts @@ -41,6 +41,7 @@ const mockedRemoveArchiveEntries = removeArchiveEntries as jest.MockedFunction< >; let soClient: jest.Mocked; let esClient: jest.Mocked; +let alertingRulesClient: any; const assetsMap = new Map([ [ @@ -111,6 +112,10 @@ describe('stepSaveArchiveEntries', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedSaveArchiveEntriesFromAssetsMap).mockReset(); @@ -149,6 +154,7 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -192,6 +198,7 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -241,6 +248,7 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -314,6 +322,7 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -342,6 +351,7 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -368,6 +378,7 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -392,6 +403,7 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -417,6 +429,7 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts index 49b1ee84d88c5..52718eb576512 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts @@ -32,12 +32,17 @@ const mockedPackagePolicyService = packagePolicyService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); beforeEach(async () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(() => { @@ -64,6 +69,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -131,6 +137,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts index 017805d34efef..1f07c6b02ec46 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts @@ -43,6 +43,8 @@ const createMockTemplate = ({ name, composedOf = [] }: { name: string; composedO describe('stepUpdateCurrentWriteIndices', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; + const getMockInstalledPackageSo = ( installedEs: EsAssetReference[] = [] ): SavedObject => { @@ -68,6 +70,10 @@ describe('stepUpdateCurrentWriteIndices', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(async () => { jest.mocked(mockedUpdateCurrentWriteIndices).mockReset(); @@ -120,6 +126,7 @@ describe('stepUpdateCurrentWriteIndices', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -144,6 +151,7 @@ describe('stepUpdateCurrentWriteIndices', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts index 887ae21cd5e2a..1ec783abd754d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts @@ -42,12 +42,17 @@ const mockedAuditLoggingService = auditLoggingService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; + let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); beforeEach(async () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); + alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); afterEach(() => { mockedAuditLoggingService.writeCustomSoAuditLog.mockReset(); @@ -60,6 +65,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -116,6 +122,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -153,6 +160,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -198,6 +206,7 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, + alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts index 0ac71cc7c5a84..2e5459492bbb2 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts @@ -18,6 +18,10 @@ jest.mock('./bundled_packages'); const mockedInstallPackage = jest.mocked(installPackage); const mockedGetBundledPackageForInstallation = jest.mocked(getBundledPackageForInstallation); +const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), +} as any; describe('reinstallPackageForInstallation', () => { beforeEach(() => { @@ -35,6 +39,7 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient, installation: { install_source: 'upload', } as Installation, @@ -49,6 +54,7 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient, installation: { install_source: 'registry', name: 'test', @@ -73,6 +79,7 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient, installation: { install_source: 'bundled', name: 'test_bundled', @@ -98,6 +105,7 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient, installation: { install_source: 'upload', name: 'test_bundled', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts index cb2b91de252f7..de6b98a49a5e9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts @@ -7,6 +7,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { Installation } from '../../../types'; import { pkgToPkgKey } from '../registry'; @@ -20,10 +21,12 @@ import { installPackage } from './install'; export async function reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient, installation, }: { soClient: SavedObjectsClientContract; esClient: ElasticsearchClient; + alertingRulesClient: RulesClientApi | null; installation: Installation; }) { if (installation.install_source === 'upload' || installation.install_source === 'bundled') { @@ -44,6 +47,7 @@ export async function reinstallPackageForInstallation({ // If the package is bundled reinstall from the registry will still use the bundled package. installSource: 'registry', savedObjectsClient: soClient, + alertingRulesClient, pkgkey: pkgToPkgKey({ name: installation.name, version: installation.version, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 8dd71e10b195a..605b885878532 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -60,7 +60,7 @@ const MAX_ASSETS_TO_DELETE = 1000; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; pkgName: string; pkgVersion?: string; esClient: ElasticsearchClient; @@ -151,7 +151,7 @@ export async function deleteKibanaAssets({ spaceId = DEFAULT_SPACE_ID, }: { installedObjects: KibanaAssetReference[]; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; logger: Logger; packageSpecConditions?: PackageSpecConditions; spaceId?: string; @@ -178,10 +178,19 @@ export async function deleteKibanaAssets({ (installedObject) => installedObject.type === KibanaSavedObjectType.alert ); + if (alertAssets.length > 0 && !alertingRulesClient) { + logger.debug( + 'Deleting alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.' + ); + } + if (minKibana && minKibana.major >= 8) { + const deleteAlertRulesPromise = alertingRulesClient + ? bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger) + : Promise.resolve(); await Promise.all([ bulkDeleteSavedObjects(soAssets, namespace, savedObjectsClient, logger), - bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger), + deleteAlertRulesPromise, ]); } else { const { resolved_objects: resolvedObjects } = await savedObjectsClient.bulkResolve( @@ -375,7 +384,7 @@ export async function deletePrerequisiteAssets( async function deleteAssets( savedObjectsClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, + alertingRulesClient: RulesClientApi | null, { installed_es: installedEs, installed_kibana: installedKibana, @@ -466,7 +475,7 @@ export async function deleteKibanaSavedObjectsAssets({ spaceId, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClientApi | null; installedPkg: SavedObject; spaceId?: string; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts index 46911e8c8a85c..500e6fbabcac9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts @@ -39,6 +39,10 @@ describe('updateCustomIntegration', () => { let mockContract: ReturnType; const savedObjectsClient = savedObjectsClientMock.create(); const esClient = elasticsearchClientMock.createElasticsearchClient(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; beforeEach(() => { mockContract = createAppContextStartContractMock(); @@ -104,10 +108,16 @@ describe('updateCustomIntegration', () => { }); it('should update custom integration with new version and readme', async () => { - const result = await updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { - readMeData: '# Updated Test Integration', - categories: ['custom'], - }); + const result = await updateCustomIntegration( + esClient, + savedObjectsClient, + alertingRulesClient, + 'test-integration', + { + readMeData: '# Updated Test Integration', + categories: ['custom'], + } + ); // Verify the updated version expect(result).toEqual({ @@ -137,6 +147,7 @@ describe('updateCustomIntegration', () => { const result = await incrementVersionAndUpdate( savedObjectsClient, esClient, + alertingRulesClient, 'test-integration', { readme: '# Updated Test Integration', @@ -164,9 +175,15 @@ describe('updateCustomIntegration', () => { }); await expect( - updateCustomIntegration(esClient, savedObjectsClient, 'non-existent-integration', { - readMeData: '# Updated Test Integration', - }) + updateCustomIntegration( + esClient, + savedObjectsClient, + alertingRulesClient, + 'non-existent-integration', + { + readMeData: '# Updated Test Integration', + } + ) ).rejects.toThrow('Integration with ID non-existent-integration not found'); }); @@ -175,9 +192,15 @@ describe('updateCustomIntegration', () => { mockGetInstalledPackageWithAssets.mockRejectedValueOnce(testError); await expect( - updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { - readMeData: '# Updated Test Integration', - }) + updateCustomIntegration( + esClient, + savedObjectsClient, + alertingRulesClient, + 'test-integration', + { + readMeData: '# Updated Test Integration', + } + ) ).rejects.toThrow('Test error during update'); }); @@ -196,9 +219,15 @@ describe('updateCustomIntegration', () => { }); await expect( - updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { - readMeData: '# Updated Test Integration', - }) + updateCustomIntegration( + esClient, + savedObjectsClient, + alertingRulesClient, + 'test-integration', + { + readMeData: '# Updated Test Integration', + } + ) ).rejects.toThrow('Integration with ID test-integration is not a custom integration'); }); }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts index a53fdd1294fda..80f58ac410efc 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts @@ -10,6 +10,7 @@ import type { SavedObjectsClientContract, } from '@kbn/core/server'; import { load, dump } from 'js-yaml'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { PACKAGES_SAVED_OBJECT_TYPE, @@ -40,6 +41,7 @@ import { installPackageWithStateMachine } from './install'; export async function updateCustomIntegration( esClient: ElasticsearchClient, soClient: SavedObjectsClientContract, + alertingRulesClient: RulesClientApi, id: string, fields: { readMeData?: string; @@ -70,7 +72,7 @@ export async function updateCustomIntegration( newVersion[2] = (parseInt(newVersion[2], 10) + 1).toString(); const newVersionString = newVersion.join('.'); // Increment the version of everything and create a new package - const res = await incrementVersionAndUpdate(soClient, esClient, id, { + const res = await incrementVersionAndUpdate(soClient, esClient, alertingRulesClient, id, { version: newVersionString, readme: fields.readMeData, categories: fields.categories, @@ -84,6 +86,7 @@ export async function updateCustomIntegration( export async function incrementVersionAndUpdate( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, + alertingRulesClient: RulesClientApi, pkgName: string, data: { version: string; @@ -173,6 +176,7 @@ export async function incrementVersionAndUpdate( installType: 'install', savedObjectsClient: soClient, esClient, + alertingRulesClient, spaceId: 'default', force: true, paths: packageInstallContext.paths, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts index 12f1abf0dfa7e..d130f1bda1fa6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts @@ -273,6 +273,10 @@ describe('Package policy service', () => { it('should call audit logger', async () => { const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const soClient = createSavedObjectClientMock(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; soClient.create.mockResolvedValueOnce({ id: 'test-package-policy', @@ -286,6 +290,7 @@ describe('Package policy service', () => { await packagePolicyService.create( soClient, esClient, + alertingRulesClient, { name: 'Test Package Policy', namespace: 'test', @@ -316,6 +321,10 @@ describe('Package policy service', () => { const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const soClient = createSavedObjectClientMock(); + const alertingRulesClient = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + } as any; soClient.create.mockResolvedValueOnce({ id: 'test-package-policy', @@ -330,6 +339,7 @@ describe('Package policy service', () => { packagePolicyService.create( soClient, esClient, + alertingRulesClient, { name: 'Test Package Policy', namespace: 'test', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts index 1c31f409f7608..1f6a43650356c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts @@ -71,7 +71,7 @@ export interface PackagePolicyClient { create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClientApi: RulesClientApi, + alertingRulesClientApi: RulesClientApi | null, packagePolicy: NewPackagePolicy, options?: { spaceId?: string; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts b/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts index cf0ee7e70ca15..e5b4aa720fd90 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts @@ -99,6 +99,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( savedObjectsClient: defaultSoClient, esClient, packagesToInstall, + alertingRulesClient: null, force: true, // Always force outdated packages to be installed if a later version isn't installed skipIfInstalled: true, // force flag alone would reinstall packages that are already installed spaceId, @@ -128,7 +129,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( // will occur between upgrading the package and reinstalling the previously failed package. // By moving this outside of the Promise.all, the upgrade will occur first, and then we'll attempt to reinstall any // packages that are stuck in the installing state. - await ensurePackagesCompletedInstall(defaultSoClient, esClient); + await ensurePackagesCompletedInstall(defaultSoClient, esClient, null); // Create policies specified in Kibana config logger.debug(`Creating preconfigured policies`); @@ -188,6 +189,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( const updatedPolicy = await agentPolicyService.update( namespacedSoClient, esClient, + null, String(preconfiguredAgentPolicy.id), newFields, { @@ -305,6 +307,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( await agentPolicyService.update( namespacedSoClient, esClient, + null, policy!.id, { is_managed: true }, { @@ -396,6 +399,7 @@ async function addPreconfiguredPolicyPackages( await addPackageToAgentPolicy( namespacedSoClient, esClient, + null, agentPolicy, packageInfo, name, @@ -420,7 +424,7 @@ async function addPreconfiguredPolicyPackages( {} ); - await packagePolicyService.create(namespacedSoClient, esClient, newPackagePolicy, { + await packagePolicyService.create(namespacedSoClient, esClient, null, newPackagePolicy, { id, bumpRevision: bumpAgentPolicyRevison, skipEnsureInstalled: true, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/setup.ts b/x-pack/platform/plugins/shared/fleet/server/services/setup.ts index 929abc9aa2df4..34d12ba67c8f3 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/setup.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/setup.ts @@ -332,6 +332,7 @@ export async function ensureFleetGlobalEsAssets( await reinstallPackageForInstallation({ soClient, esClient, + alertingRulesClient: null, installation, }).catch((err) => { apm.captureError(err); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts index 0e16f88101685..7fd5856dd1c0f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts @@ -31,7 +31,6 @@ describe('syncIntegrationsOnRemote', () => { let packageClientMock: any; let loggerMock: any; let soClientMock: any; - let alertingRulesClientMock: any; beforeEach(() => { getIndicesMock = jest.fn(); @@ -64,10 +63,6 @@ describe('syncIntegrationsOnRemote', () => { soClientMock = { update: jest.fn(), }; - alertingRulesClientMock = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); it('should throw error if multiple synced integrations ccr indices exist', async () => { @@ -77,14 +72,7 @@ describe('syncIntegrationsOnRemote', () => { }); await expect( - syncIntegrationsOnRemote( - esClientMock, - soClientMock, - alertingRulesClientMock, - {} as any, - abortController, - loggerMock - ) + syncIntegrationsOnRemote(esClientMock, soClientMock, {} as any, abortController, loggerMock) ).rejects.toThrowError( 'Not supported to sync multiple indices with prefix fleet-synced-integrations-ccr-*' ); @@ -156,7 +144,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -185,7 +172,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -217,7 +203,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -260,7 +245,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -296,7 +280,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -329,7 +312,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -366,7 +348,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -391,7 +372,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -441,7 +421,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -487,7 +466,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -524,7 +502,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -561,7 +538,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 32b8efe1484e8..598d98c7dca72 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -215,6 +215,7 @@ async function uninstallPackageIfInstalled( savedObjectsClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, + alertingRulesClient: null, esClient, force: false, }); From 43611a33a7fcdcc44280134345a58674ca65979d Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:45:13 -0700 Subject: [PATCH 15/41] Revert "WIP: Have alertingRulesClient be optional for package install to support non-request contexts" This reverts commit ab73d22d61dadf79aacf65abd72f80ba84665600. --- .../context/fixtures/integration.nginx.ts | 1 - .../context/fixtures/integration.okta.ts | 1 - .../shared/fleet/server/mocks/index.ts | 2 - .../plugins/shared/fleet/server/plugin.ts | 8 +-- .../fleet/server/routes/epm/index.test.ts | 1 - .../routes/epm/kibana_assets_handler.ts | 8 --- .../routes/package_policy/handlers.test.ts | 2 +- .../server/routes/package_policy/handlers.ts | 5 -- .../server/services/agent_policy.test.ts | 59 +++++++------------ .../fleet/server/services/agent_policy.ts | 48 ++++----------- .../services/agent_policy_create.test.ts | 27 ++------- .../server/services/agent_policy_create.ts | 46 +++++---------- .../epm/kibana/assets/install.test.ts | 6 +- .../services/epm/kibana/assets/install.ts | 28 ++++----- .../kibana/assets/install_with_streaming.ts | 12 +--- .../services/epm/package_service.test.ts | 12 +--- .../server/services/epm/package_service.ts | 27 +++------ .../packages/bulk_install_packages.test.ts | 7 --- .../epm/packages/bulk_install_packages.ts | 4 -- .../epm/packages/input_type_packages.test.ts | 11 ---- .../epm/packages/input_type_packages.ts | 6 +- .../services/epm/packages/install.test.ts | 31 ---------- .../server/services/epm/packages/install.ts | 14 ++--- .../_state_machine_package_install.test.ts | 10 ---- .../_state_machine_package_install.ts | 2 +- .../step_create_restart_installation.test.ts | 9 --- .../step_delete_previous_pipelines.test.ts | 14 ----- .../steps/step_install_ilm_policies.test.ts | 14 ----- ...p_install_index_template_pipelines.test.ts | 15 ----- .../steps/step_install_kibana_assets.test.ts | 14 ----- .../steps/step_install_mlmodel.test.ts | 12 ---- .../steps/step_install_transforms.test.ts | 12 ---- .../step_remove_legacy_templates.test.ts | 7 --- .../steps/step_save_archive_entries.test.ts | 13 ---- .../steps/step_save_system_object.test.ts | 7 --- .../step_update_current_write_indices.test.ts | 8 --- .../update_latest_executed_state.test.ts | 9 --- .../services/epm/packages/reinstall.test.ts | 8 --- .../server/services/epm/packages/reinstall.ts | 4 -- .../server/services/epm/packages/remove.ts | 19 ++---- .../update_custom_integration.test.ts | 55 ++++------------- .../epm/packages/update_custom_integration.ts | 6 +- .../server/services/package_policy.test.ts | 10 ---- .../server/services/package_policy_service.ts | 2 +- .../fleet/server/services/preconfiguration.ts | 8 +-- .../shared/fleet/server/services/setup.ts | 1 - .../sync_integrations_on_remote.test.ts | 26 +++++++- .../sync_integrations_on_remote.ts | 1 - 48 files changed, 139 insertions(+), 513 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts index 87d770d032074..ea89331156566 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts @@ -80,7 +80,6 @@ export const item: GetInfoResponse['item'] = { // path: 'nginx-0.7.0/kibana/dashboard/nginx-55a9e6e0-a29e-11e7-928f-5dbe6f6f5519.json', }, ], - alert: [], ml_module: [ { pkgkey: 'nginx-0.7.0', diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts index 285857f81cd89..ddae02803faf0 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts @@ -52,7 +52,6 @@ export const item: GetInfoResponse['item'] = { // path: 'okta-1.2.0/kibana/dashboard/okta-749203a0-67b1-11ea-a76f-bf44814e437d.json', }, ], - alert: [], map: [ { pkgkey: 'okta-1.2.0', diff --git a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts index a3318b10ad51e..8bfccc605f3b5 100644 --- a/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts +++ b/x-pack/platform/plugins/shared/fleet/server/mocks/index.ts @@ -19,7 +19,6 @@ import { licensingMock } from '@kbn/licensing-plugin/server/mocks'; import { encryptedSavedObjectsMock } from '@kbn/encrypted-saved-objects-plugin/server/mocks'; import { securityMock } from '@kbn/security-plugin/server/mocks'; import { cloudMock } from '@kbn/cloud-plugin/public/mocks'; -import { alertsMock } from '@kbn/alerting-plugin/server/mocks'; import { SPACES_EXTENSION_ID } from '@kbn/core-saved-objects-server'; import type { SavedObjectsClientContract } from '@kbn/core-saved-objects-api-server'; @@ -149,7 +148,6 @@ export const createAppContextStartContractMock = ( encryptedSavedObjectsStart: encryptedSavedObjectsMock.createStart(), encryptedSavedObjectsSetup: encryptedSavedObjectsMock.createSetup({ canEncrypt: true }), savedObjects: mockedSavedObject, - alertingStart: alertsMock.createStart(), securityCoreStart: securityServiceMock.createStart(), securitySetup: securityMock.createSetup(), securityStart: securityMock.createStart(), diff --git a/x-pack/platform/plugins/shared/fleet/server/plugin.ts b/x-pack/platform/plugins/shared/fleet/server/plugin.ts index bc16d3bf68791..4825753815761 100644 --- a/x-pack/platform/plugins/shared/fleet/server/plugin.ts +++ b/x-pack/platform/plugins/shared/fleet/server/plugin.ts @@ -51,6 +51,7 @@ import type { import type { CloudSetup } from '@kbn/cloud-plugin/server'; import type { SpacesPluginStart } from '@kbn/spaces-plugin/server'; import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/server'; + import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server'; import { KibanaFeatureScope } from '@kbn/features-plugin/common'; @@ -872,8 +873,7 @@ export class FleetPlugin fleetSetupCompleted: () => fleetSetupPromise, packageService: this.setupPackageService( core.elasticsearch.client.asInternalUser, - internalSoClient, - plugins.alerting + internalSoClient ), agentService: this.setupAgentService( core.elasticsearch.client.asInternalUser, @@ -937,8 +937,7 @@ export class FleetPlugin private setupPackageService( internalEsClient: ElasticsearchClient, - internalSoClient: SavedObjectsClientContract, - alertingStart: AlertingServerStart + internalSoClient: SavedObjectsClientContract ): PackageService { if (this.packageService) { return this.packageService; @@ -947,7 +946,6 @@ export class FleetPlugin this.packageService = new PackageServiceImpl( internalEsClient, internalSoClient, - alertingStart, this.getLogger() ); return this.packageService!; diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts index c762bf182f15d..96e25bfdc8c2a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts @@ -190,7 +190,6 @@ describe('schema validation', () => { const assets: AssetsGroupedByServiceByType = { kibana: { dashboard: [], - alert: [], visualization: [], search: [], lens: [], diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts index 68fdbe5a7c8b8..71de2f640a962 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/kibana_assets_handler.ts @@ -47,9 +47,6 @@ export const installPackageKibanaAssetsHandler: FleetRequestHandler< > = async (context, request, response) => { const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const logger = appContextService.getLogger(); const spaceId = fleetContext.spaceId; const { pkgName, pkgVersion } = request.params; @@ -84,7 +81,6 @@ export const installPackageKibanaAssetsHandler: FleetRequestHandler< for (const spaceToInstallId of spaceIds) { await installKibanaAssetsAndReferences({ savedObjectsClient: appContextService.getInternalUserSOClientForSpaceId(spaceToInstallId), - alertingRulesClient, logger, pkgName, pkgTitle: packageInfo.title, @@ -109,9 +105,6 @@ export const deletePackageKibanaAssetsHandler: FleetRequestHandler< > = async (context, request, response) => { const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const logger = appContextService.getLogger(); const spaceId = fleetContext.spaceId; const { pkgName, pkgVersion } = request.params; @@ -127,7 +120,6 @@ export const deletePackageKibanaAssetsHandler: FleetRequestHandler< await deleteKibanaAssetsAndReferencesForSpace({ savedObjectsClient, - alertingRulesClient, logger, pkgName, spaceId, diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts index a4d15ccf407e8..e8904d82a7632 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.test.ts @@ -92,7 +92,7 @@ jest.mock( ), buildPackagePolicyFromPackage: jest.fn(), bulkCreate: jest.fn(), - create: jest.fn((soClient, esClient, alertingRulesClient, newData) => + create: jest.fn((soClient, esClient, newData) => Promise.resolve({ ...newData, inputs: newData.inputs.map((input) => ({ diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts index 5e16f9e1887a5..117ff3c219631 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/package_policy/handlers.ts @@ -226,9 +226,6 @@ export const createPackagePolicyHandler: FleetRequestHandler< const fleetContext = await context.fleet; const soClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; const { force, id, package: pkg, ...newPolicy } = request.body; if ('spaceIds' in newPolicy) { @@ -273,7 +270,6 @@ export const createPackagePolicyHandler: FleetRequestHandler< const packagePolicy = await fleetContext.packagePolicyService.asCurrentUser.create( soClient, esClient, - alertingRulesClient, newPackagePolicy, { id, @@ -308,7 +304,6 @@ export const createPackagePolicyHandler: FleetRequestHandler< .info(`rollback ${pkg!.name}-${pkg!.version} package installation after error`); await removeInstallation({ savedObjectsClient: soClient, - alertingRulesClient, pkgName: pkg!.name, pkgVersion: pkg!.version, esClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts index 844faa3c21a3c..8ca7af0a29edc 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.test.ts @@ -162,11 +162,6 @@ function getAgentPolicyCreateMock() { } let mockedLogger: jest.Mocked; -const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), -} as any; - describe('Agent policy', () => { beforeEach(() => { mockedLogger = loggerMock.create(); @@ -928,7 +923,7 @@ describe('Agent policy', () => { soClient ); mockedAppContextService.getInternalUserSOClientForSpaceId.mockReturnValue(soClient); - await agentPolicyService.removeOutputFromAll(esClient, alertingRulesClient, 'output-id-123'); + await agentPolicyService.removeOutputFromAll(esClient, 'output-id-123'); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledTimes(2); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledWith( @@ -989,11 +984,7 @@ describe('Agent policy', () => { ], } as any); - await agentPolicyService.removeDefaultSourceFromAll( - esClient, - alertingRulesClient, - 'default-download-source-id' - ); + await agentPolicyService.removeDefaultSourceFromAll(esClient, 'default-download-source-id'); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledTimes(2); expect(mockedAgentPolicyServiceUpdate).toHaveBeenCalledWith( @@ -1044,7 +1035,7 @@ describe('Agent policy', () => { }, ], }); - await agentPolicyService.update(soClient, esClient, alertingRulesClient, 'mocked', { + await agentPolicyService.update(soClient, esClient, 'mocked', { name: 'mocked', namespace: 'default', is_managed: false, @@ -1053,7 +1044,7 @@ describe('Agent policy', () => { let calledWith = soClient.update.mock.calls[0]; expect(calledWith[2]).toHaveProperty('is_managed', false); - await agentPolicyService.update(soClient, esClient, alertingRulesClient, 'mocked', { + await agentPolicyService.update(soClient, esClient, 'mocked', { name: 'is_managed: true provided', namespace: 'default', is_managed: true, @@ -1080,7 +1071,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { is_protected: true, }) ).rejects.toThrowError( @@ -1105,17 +1096,11 @@ describe('Agent policy', () => { ], }); - await agentPolicyService.update( - soClient, - esClient, - alertingRulesClient, - 'test-agent-policy', - { - name: 'Test Agent Policy', - namespace: 'default', - is_managed: false, - } - ); + await agentPolicyService.update(soClient, esClient, 'test-agent-policy', { + name: 'Test Agent Policy', + namespace: 'default', + is_managed: false, + }); expect(mockedAuditLoggingService.writeCustomSoAuditLog).toHaveBeenCalledWith({ action: 'update', @@ -1143,7 +1128,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', is_protected: true, @@ -1171,7 +1156,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', }) @@ -1204,7 +1189,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', is_protected: true, @@ -1234,7 +1219,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1264,7 +1249,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1295,7 +1280,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', supports_agentless: true, @@ -1326,7 +1311,7 @@ describe('Agent policy', () => { }); await expect( - agentPolicyService.update(soClient, esClient, alertingRulesClient, 'test-id', { + agentPolicyService.update(soClient, esClient, 'test-id', { name: 'test', namespace: 'default', }) @@ -1357,7 +1342,7 @@ describe('Agent policy', () => { }, ] as any); try { - await agentPolicyService.copy(soClient, esClient, alertingRulesClient, 'mocked', { + await agentPolicyService.copy(soClient, esClient, 'mocked', { name: 'copy mocked', }); } catch (e) { @@ -1436,7 +1421,7 @@ describe('Agent policy', () => { ] as any; mockedPackagePolicyService.findAllForAgentPolicy.mockReturnValue(packagePolicies); mockedPackagePolicyService.list.mockResolvedValue({ items: packagePolicies } as any); - await agentPolicyService.copy(soClient, esClient, alertingRulesClient, 'mocked', { + await agentPolicyService.copy(soClient, esClient, 'mocked', { name: 'copy mocked', }); expect(mockedPackagePolicyService.bulkCreate).toBeCalledWith( @@ -1509,7 +1494,7 @@ describe('Agent policy', () => { soClient.bulkGet.mockResolvedValue({ saved_objects: [mockSo], }); - await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'policy123'); + await agentPolicyService.deployPolicy(soClient, 'policy123'); expect(esClient.create).not.toBeCalled(); }); @@ -1561,7 +1546,7 @@ describe('Agent policy', () => { soClient.bulkGet.mockResolvedValue({ saved_objects: [mockSo], }); - await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'policy123'); + await agentPolicyService.deployPolicy(soClient, 'policy123'); expect(esClient.bulk).toBeCalledWith( expect.objectContaining({ @@ -1609,7 +1594,7 @@ describe('Agent policy', () => { ], }); - await agentPolicyService.deployPolicy(soClient, alertingRulesClient, 'test-agent-policy'); + await agentPolicyService.deployPolicy(soClient, 'test-agent-policy'); expect(mockedAuditLoggingService.writeCustomAuditLog).toHaveBeenCalledWith({ message: `User deploying policy [id=test-agent-policy]`, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts index eb4d1c9cc661e..2473db96d9073 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy.ts @@ -23,10 +23,13 @@ import type { } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { SavedObjectsUtils } from '@kbn/core/server'; + import type { BulkResponseItem } from '@elastic/elasticsearch/lib/api/types'; + import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; + import type { SavedObjectError } from '@kbn/core-saved-objects-common'; + import { withSpan } from '@kbn/apm-utils'; import { catchAndSetErrorStackTrace } from '../errors/utils'; @@ -822,7 +825,6 @@ class AgentPolicyService { public async update( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi | null, id: string, agentPolicy: Partial, options?: { @@ -896,7 +898,6 @@ class AgentPolicyService { await bulkInstallPackages({ savedObjectsClient: soClient, esClient, - alertingRulesClient, packagesToInstall, spaceId: options?.spaceId || DEFAULT_SPACE_ID, authorizationHeader: options?.authorizationHeader, @@ -924,7 +925,6 @@ class AgentPolicyService { public async copy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, id: string, newAgentPolicyProps: Pick, options?: { user?: AuthenticatedUser } @@ -1044,7 +1044,7 @@ class AgentPolicyService { user: options?.user, }); } else { - await this.deployPolicy(soClient, alertingRulesClient, newAgentPolicy.id); + await this.deployPolicy(soClient, newAgentPolicy.id); } // Get updated agent policy with package policies and adjusted tamper protection @@ -1086,7 +1086,6 @@ class AgentPolicyService { */ public async removeOutputFromAll( esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, outputId: string, options?: { force?: boolean } ) { @@ -1140,17 +1139,10 @@ class AgentPolicyService { const soClient = appContextService.getInternalUserSOClientForSpaceId( agentPolicy.space_ids?.[0] ); - return this.update( - soClient, - esClient, - alertingRulesClient, - agentPolicy.id, - getAgentPolicy(agentPolicy), - { - skipValidation: true, - force: options?.force, - } - ); + return this.update(soClient, esClient, agentPolicy.id, getAgentPolicy(agentPolicy), { + skipValidation: true, + force: options?.force, + }); }, { concurrency: MAX_CONCURRENT_AGENT_POLICIES_OPERATIONS, @@ -1164,7 +1156,6 @@ class AgentPolicyService { */ public async removeFleetServerHostFromAll( esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, fleetServerHostId: string, options?: { force?: boolean } ) { @@ -1189,7 +1180,6 @@ class AgentPolicyService { this.update( appContextService.getInternalUserSOClientForSpaceId(agentPolicy.space_ids?.[0]), esClient, - alertingRulesClient, agentPolicy.id, { fleet_server_host_id: null, @@ -1499,21 +1489,14 @@ class AgentPolicyService { public async deployPolicy( soClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, agentPolicyId: string, agentPolicy?: AgentPolicy | null ) { - await this.deployPolicies( - soClient, - alertingRulesClient, - [agentPolicyId], - agentPolicy ? [agentPolicy] : undefined - ); + await this.deployPolicies(soClient, [agentPolicyId], agentPolicy ? [agentPolicy] : undefined); } public async deployPolicies( soClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, agentPolicyIds: string[], agentPolicies?: AgentPolicy[] ) { @@ -1657,7 +1640,6 @@ class AgentPolicyService { return agentPolicyService.update( soClient, esClient, - alertingRulesClient, fleetServerPolicy.policy_id, { schema_version: FLEET_AGENT_POLICIES_SCHEMA_VERSION, @@ -1780,11 +1762,7 @@ class AgentPolicyService { * @param esClient * @param downloadSourceId */ - public async removeDefaultSourceFromAll( - esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, - downloadSourceId: string - ) { + public async removeDefaultSourceFromAll(esClient: ElasticsearchClient, downloadSourceId: string) { const savedObjectType = await getAgentPolicySavedObjectType(); const agentPolicies = ( await appContextService @@ -1806,7 +1784,6 @@ class AgentPolicyService { this.update( appContextService.getInternalUserSOClientForSpaceId(agentPolicy.space_ids?.[0]), esClient, - alertingRulesClient, agentPolicy.id, { download_source_id: @@ -2208,7 +2185,6 @@ export const agentPolicyService = new AgentPolicyService(); export async function addPackageToAgentPolicy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi | null, agentPolicy: AgentPolicy, packageInfo: PackageInfo, packagePolicyName?: string, @@ -2235,7 +2211,7 @@ export async function addPackageToAgentPolicy( ? String(packagePolicyId) : uuidv5(`${agentPolicy.id}-${packagePolicyName}`, UUID_V5_NAMESPACE); - await packagePolicyService.create(soClient, esClient, alertingRulesClient, newPackagePolicy, { + await packagePolicyService.create(soClient, esClient, newPackagePolicy, { id, bumpRevision: bumpAgentPolicyRevison, skipEnsureInstalled: true, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts index 709e3df016439..aa85bbbf6c56d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.test.ts @@ -60,10 +60,6 @@ function getPackagePolicy(name: string, policyId = '') { describe('createAgentPolicyWithPackages', () => { const esClientMock = elasticsearchServiceMock.createElasticsearchClient(); const soClientMock = savedObjectsClientMock.create(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; beforeEach(() => { appContextService.start(createAppContextStartContractMock()); @@ -78,17 +74,15 @@ describe('createAgentPolicyWithPackages', () => { mockedAgentPolicyService.deployPolicy.mockResolvedValue(); mockedPackagePolicyService.buildPackagePolicyFromPackage.mockImplementation( - (soClient, _alertingRulesClient, packageToInstall) => - Promise.resolve(getPackagePolicy(packageToInstall)) + (soClient, packageToInstall) => Promise.resolve(getPackagePolicy(packageToInstall)) ); mockIncrementPackageName.mockImplementation((soClient: any, pkg: string) => Promise.resolve(`${pkg}-1`) ); - mockedPackagePolicyService.create.mockImplementation( - (soClient, esClient, _alertingRulesClient, newPolicy) => - Promise.resolve({ - ...newPolicy, - } as PackagePolicy) + mockedPackagePolicyService.create.mockImplementation((soClient, esClient, newPolicy) => + Promise.resolve({ + ...newPolicy, + } as PackagePolicy) ); }); @@ -105,7 +99,6 @@ describe('createAgentPolicyWithPackages', () => { await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -128,7 +121,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Fleet Server policy', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: true, @@ -162,7 +154,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Fleet Server policy 2', namespace: 'default' }, hasFleetServer: true, withSysMonitoring: false, @@ -188,7 +179,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -214,7 +204,7 @@ describe('createAgentPolicyWithPackages', () => { mockedAgentPolicyService.create.mockImplementation( async (soClient, esClient, newPolicy, options) => { if (!options?.skipDeploy) { - await mockedAgentPolicyService.deployPolicy(soClientMock, alertingRulesClient, 'new_id'); + await mockedAgentPolicyService.deployPolicy(soClientMock, 'new_id'); } return Promise.resolve({ ...newPolicy, @@ -225,7 +215,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -245,7 +234,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: true, spaceId: 'default', @@ -271,7 +259,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -285,7 +272,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { id: 'policy-1', name: 'Agent policy 1', namespace: 'default' }, withSysMonitoring: false, spaceId: 'default', @@ -305,7 +291,6 @@ describe('createAgentPolicyWithPackages', () => { const response = await createAgentPolicyWithPackages({ esClient: esClientMock, soClient: soClientMock, - alertingRulesClient, newPolicy: { id: 'new_fleet_server_policy', name: 'Fleet Server policy', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts index 65a5e707edfb7..07f93852356ae 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/agent_policy_create.ts @@ -10,7 +10,6 @@ import type { ElasticsearchClient, SavedObjectsClientContract, } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { getDefaultFleetServerpolicyId } from '../../common/services/agent_policies_helpers'; import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header'; @@ -66,7 +65,6 @@ async function getFleetServerAgentPolicyId( async function createPackagePolicy( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, agentPolicy: AgentPolicy, packageToInstall: string, options: { @@ -77,7 +75,7 @@ async function createPackagePolicy( } ) { const newPackagePolicy = await packagePolicyService - .buildPackagePolicyFromPackage(soClient, alertingRulesClient, packageToInstall) + .buildPackagePolicyFromPackage(soClient, packageToInstall) .catch(async (error) => { // rollback agent policy on error await agentPolicyService.delete(soClient, esClient, agentPolicy.id, { @@ -96,7 +94,7 @@ async function createPackagePolicy( newPackagePolicy.supports_agentless = agentPolicy.supports_agentless; } - await packagePolicyService.create(soClient, esClient, alertingRulesClient, newPackagePolicy, { + await packagePolicyService.create(soClient, esClient, newPackagePolicy, { spaceId: options.spaceId, user: options.user, bumpRevision: false, @@ -108,7 +106,6 @@ async function createPackagePolicy( interface CreateAgentPolicyParams { soClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; newPolicy: NewAgentPolicy; hasFleetServer?: boolean; withSysMonitoring: boolean; @@ -122,7 +119,6 @@ interface CreateAgentPolicyParams { export async function createAgentPolicyWithPackages({ soClient, esClient, - alertingRulesClient, newPolicy, hasFleetServer, withSysMonitoring, @@ -183,36 +179,22 @@ export async function createAgentPolicyWithPackages({ // Create the fleet server package policy and add it to agent policy. if (hasFleetServer) { - await createPackagePolicy( - soClient, - esClient, - alertingRulesClient, - agentPolicy, - FLEET_SERVER_PACKAGE, - { - spaceId, - user, - authorizationHeader, - force, - } - ); + await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SERVER_PACKAGE, { + spaceId, + user, + authorizationHeader, + force, + }); } // Create the system monitoring package policy and add it to agent policy. if (withSysMonitoring) { - await createPackagePolicy( - soClient, - esClient, - alertingRulesClient, - agentPolicy, - FLEET_SYSTEM_PACKAGE, - { - spaceId, - user, - authorizationHeader, - force, - } - ); + await createPackagePolicy(soClient, esClient, agentPolicy, FLEET_SYSTEM_PACKAGE, { + spaceId, + user, + authorizationHeader, + force, + }); } await ensureDefaultEnrollmentAPIKeyForAgentPolicy(soClient, esClient, agentPolicy.id); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts index ce9b484005013..3b200ac5115cf 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts @@ -12,7 +12,7 @@ import type { } from '@kbn/core/server'; import { loggingSystemMock } from '@kbn/core/server/mocks'; -import type { SavedObjectAsset, ArchiveAsset } from './install'; +import { type ArchiveAsset } from './install'; jest.mock('timers/promises', () => ({ async setTimeout() {}, @@ -31,8 +31,8 @@ const createImportError = (so: ArchiveAsset, type: string) => ({ id: so.id, error: { type } } as SavedObjectsImportFailure); const createImportSuccess = (so: ArchiveAsset) => ({ id: so.id, type: so.type, meta: {} } as SavedObjectsImportSuccess); -const createAsset = (asset: Partial) => - ({ id: 1234, type: 'dashboard', attributes: {}, ...asset } as SavedObjectAsset); +const createAsset = (asset: Partial) => + ({ id: 1234, type: 'dashboard', attributes: {}, ...asset } as ArchiveAsset); const createImportResponse = ( errors: SavedObjectsImportFailure[] = [], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index fe6b6584eec96..1b0b5d2377304 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -138,7 +138,7 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; spaceId: string; @@ -172,21 +172,13 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - let installedAlertRules: ObjectReference[] = []; - - if (alertingRulesClient) { - installedAlertRules = await installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets: asAlertRules, - assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, - context: { pkgName, spaceId, assetTags }, - }); - } else if (asAlertRules.length) { - logger.debug( - `Installing ${asAlertRules.length} alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.` - ); - } + const installedAlertRules = await installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets: asAlertRules, + assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, + context: { pkgName, spaceId, assetTags }, + }); const installedAssets = await installKibanaSavedObjects({ logger, @@ -259,7 +251,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; pkgTitle: string; @@ -330,7 +322,7 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; pkgTitle: string; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index 27fd8bf1b66db..f24e2107a022a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -32,7 +32,7 @@ interface InstallKibanaAssetsWithStreamingArgs { packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; @@ -89,7 +89,7 @@ export async function installKibanaAssetsWithStreaming({ } }); - if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS && alertingRulesClient) { + if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS) { await installAlertRules({ logger, alertingRulesClient, @@ -110,13 +110,7 @@ export async function installKibanaAssetsWithStreaming({ }); } - if (alertRuleBatch.length && !alertingRulesClient) { - logger.debug( - `Installing ${alertRuleBatch.length} alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.` - ); - } - - if (alertRuleBatch.length && alertingRulesClient) { + if (alertRuleBatch.length) { await installAlertRules({ logger, alertingRulesClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts index 75d14c15cb3e3..ea7586b9ebd78 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.test.ts @@ -21,7 +21,6 @@ import { loggingSystemMock, savedObjectsClientMock, } from '@kbn/core/server/mocks'; -import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { FleetUnauthorizedError } from '../../errors'; import type { InstallablePackage } from '../../types'; @@ -238,22 +237,13 @@ describe('PackageService', () => { let mockPackageService: PackageService; let mockEsClient: ElasticsearchClient; let mockSoClient: SavedObjectsClientContract; - let mockAlertingStart: AlertingServerStart; let mockLogger: MockedLogger; beforeEach(() => { mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); mockSoClient = savedObjectsClientMock.create(); mockLogger = loggingSystemMock.createLogger(); - mockAlertingStart = { - getRulesClientWithRequest: jest.fn(), - } as any; - mockPackageService = new PackageServiceImpl( - mockEsClient, - mockSoClient, - mockAlertingStart, - mockLogger - ); + mockPackageService = new PackageServiceImpl(mockEsClient, mockSoClient, mockLogger); }); afterEach(() => { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts index 8c2aa8409ce21..7e3d29f78a3e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts @@ -15,8 +15,8 @@ import type { } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { TypeOf } from '@kbn/config-schema'; -import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import { HTTPAuthorizationHeader } from '../../../common/http_authorization_header'; @@ -161,7 +161,7 @@ export class PackageServiceImpl implements PackageService { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingStart: AlertingServerStart, + private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger ) {} @@ -186,7 +186,7 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, - this.alertingStart, + this.alertingRulesClient, this.logger, preflightCheck, request @@ -197,7 +197,7 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, - this.alertingStart, + this.alertingRulesClient, this.logger ); } @@ -209,7 +209,7 @@ class PackageClientImpl implements PackageClient { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingStart: AlertingServerStart, + private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger, private readonly preflightCheck?: ( requiredAuthz?: FleetAuthzRouteConfig['fleetAuthz'] @@ -242,15 +242,12 @@ class PackageClientImpl implements PackageClient { force?: boolean; }): Promise { await this.#runPreflight(INSTALL_PACKAGES_AUTHZ); - const alertingRulesClient = this.request - ? await this.alertingStart.getRulesClientWithRequest(this.request) - : null; return ensureInstalledPackage({ ...options, esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient, + alertingRulesClient: this.alertingRulesClient, }); } @@ -281,10 +278,6 @@ class PackageClientImpl implements PackageClient { : await Registry.fetchFindLatestPackageOrThrow(pkgName, { prerelease: true }); const pkgkey = Registry.pkgToPkgKey(pkgKeyProps); - const alertingRulesClient = this.request - ? await this.alertingStart.getRulesClientWithRequest(this.request) - : null; - return await installPackage({ force, pkgkey, @@ -292,7 +285,7 @@ class PackageClientImpl implements PackageClient { installSource: 'registry', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient, + alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, keepFailedInstallation, useStreaming, @@ -317,10 +310,6 @@ class PackageClientImpl implements PackageClient { force = false, } = options; - const alertingRulesClient = this.request - ? await this.alertingStart.getRulesClientWithRequest(this.request) - : null; - return await installPackage({ force, pkgName, @@ -330,7 +319,7 @@ class PackageClientImpl implements PackageClient { installSource: 'custom', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient, + alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, authorizationHeader: this.getAuthorizationHeader(), }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts index 3205fd015bd9d..17958699365e6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.test.ts @@ -28,10 +28,6 @@ describe('bulkInstallPackages', () => { let mockContract: ReturnType; const mockSoClient = savedObjectsClientMock.create(); const mockEsClient = elasticsearchServiceMock.createElasticsearchClient(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; beforeEach(() => { mockContract = createAppContextStartContractMock(); @@ -46,7 +42,6 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, - alertingRulesClient, packagesToInstall, esClient: mockEsClient, spaceId: 'default', @@ -65,7 +60,6 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, - alertingRulesClient, packagesToInstall, esClient: mockEsClient, spaceId: 'default', @@ -84,7 +78,6 @@ describe('bulkInstallPackages', () => { await bulkInstallPackages({ savedObjectsClient: mockSoClient, - alertingRulesClient, packagesToInstall: [...stringPackagesToInstall, ...objectPackagesToInstall], esClient: mockEsClient, spaceId: 'default', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts index 9673a17e39194..dd155da3e6b74 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/bulk_install_packages.ts @@ -6,7 +6,6 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import pLimit from 'p-limit'; import { uniqBy } from 'lodash'; @@ -23,7 +22,6 @@ import type { BulkInstallResponse, IBulkInstallPackageError } from './install'; interface BulkInstallPackagesParams { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; packagesToInstall: Array< | string | { name: string; version?: string; prerelease?: boolean; skipDataStreamRollover?: boolean } @@ -39,7 +37,6 @@ interface BulkInstallPackagesParams { export async function bulkInstallPackages({ savedObjectsClient, - alertingRulesClient, packagesToInstall, esClient, spaceId, @@ -142,7 +139,6 @@ export async function bulkInstallPackages({ const installResult = await installPackage({ savedObjectsClient, esClient, - alertingRulesClient, pkgkey, installSource: 'registry', spaceId, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts index 3aa5b10c12304..a060e902140e9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.test.ts @@ -54,11 +54,6 @@ jest.mock('../../app_context', () => { }; }); -const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), -} as any; - describe('installAssetsForInputPackagePolicy', () => { beforeEach(() => { jest.mocked(optimisticallyAddEsAssetReferences).mockReset(); @@ -177,7 +172,6 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -193,7 +187,6 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -240,7 +233,6 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).toBeCalledWith( @@ -299,7 +291,6 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).toBeCalledWith( @@ -335,7 +326,6 @@ describe('removeAssetsForInputPackagePolicy', () => { datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, logger: mockedLogger, }); expect(cleanupAssetsMock).not.toBeCalled(); @@ -359,7 +349,6 @@ describe('removeAssetsForInputPackagePolicy', () => { } as any, datasetName: 'test', savedObjectsClient: savedObjectsClientMock.create(), - alertingRulesClient, esClient: {} as ElasticsearchClient, logger: mockedLogger, }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts index 728c570b56df4..c1adc75e7d10b 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/input_type_packages.ts @@ -6,7 +6,6 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { IndicesDataStream } from 'elasticsearch-8.x/lib/api/types'; @@ -215,10 +214,8 @@ export async function removeAssetsForInputPackagePolicy(opts: { logger: Logger; esClient: ElasticsearchClient; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; }) { - const { logger, packageInfo, esClient, savedObjectsClient, alertingRulesClient, datasetName } = - opts; + const { logger, packageInfo, esClient, savedObjectsClient, datasetName } = opts; if (packageInfo.type === 'input' && packageInfo.status === 'installed') { logger.info(`Removing assets for input package ${packageInfo.name}:${packageInfo.version}`); @@ -260,7 +257,6 @@ export async function removeAssetsForInputPackagePolicy(opts: { installationToDelete, installation, esClient, - alertingRulesClient, savedObjectsClient ); } catch (error) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts index ec75d92f947df..146c1712b6513 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.test.ts @@ -163,10 +163,6 @@ describe('createInstallation', () => { }); describe('install', () => { - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; beforeEach(() => { jest .mocked(Registry.fetchFindLatestPackageOrThrow) @@ -195,7 +191,6 @@ describe('install', () => { pkgkey: 'apache-1.1.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -219,7 +214,6 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -243,7 +237,6 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -270,7 +263,6 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -297,7 +289,6 @@ describe('install', () => { pkgkey: 'apache-1.3.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -328,7 +319,6 @@ describe('install', () => { pkgkey: 'test_package-1.0.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.error).toBeUndefined(); @@ -346,7 +336,6 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.status).toEqual('installed'); @@ -376,7 +365,6 @@ describe('install', () => { pkgkey: 'apache-1.2.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.status).toEqual('already_installed'); @@ -401,7 +389,6 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.error).toBeDefined(); expect(response.error!.message).toEqual( @@ -420,7 +407,6 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, force: true, }); expect(response.error).toBeUndefined(); @@ -437,7 +423,6 @@ describe('install', () => { pkgkey: 'test_package', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.error).toBeUndefined(); }); @@ -458,7 +443,6 @@ describe('install', () => { pkgkey: 'fleet_server-2.0.0', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.status).toEqual('installed'); @@ -473,7 +457,6 @@ describe('install', () => { pkgkey: 'security_detection_engine', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(response.error).toBeUndefined(); @@ -497,7 +480,6 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -520,7 +502,6 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -547,7 +528,6 @@ describe('install', () => { contentType: '', savedObjectsClient: savedObjectsClientMock.create(), esClient: {} as ElasticsearchClient, - alertingRulesClient, }); expect(sendTelemetryEvents).toHaveBeenCalledWith(expect.anything(), undefined, { @@ -568,10 +548,6 @@ describe('install', () => { describe('handleInstallPackageFailure', () => { const mockedLogger = jest.mocked(appContextService.getLogger()); const savedObjectsClient = savedObjectsClientMock.create(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; beforeEach(() => { mockedLogger.error.mockClear(); @@ -622,7 +598,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new ConcurrentInstallOperationError('test 123'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -654,7 +629,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new FleetError('test 123'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -702,7 +676,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test 123'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -739,7 +712,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test 123'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg: undefined as any, pkgName, pkgVersion: '1.0.0', @@ -780,7 +752,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -843,7 +814,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', @@ -906,7 +876,6 @@ describe('handleInstallPackageFailure', () => { savedObjectsClient, error: new Error('test installing'), esClient: {} as ElasticsearchClient, - alertingRulesClient, installedPkg, pkgName, pkgVersion: '2.0.0', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index b2c667ab24a9d..d96aed266e310 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -175,7 +175,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -285,7 +285,7 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -408,7 +408,7 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -432,7 +432,7 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -441,7 +441,7 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -625,7 +625,7 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -1341,7 +1341,7 @@ export const saveKibanaAssetsRefs = async ( export async function ensurePackagesCompletedInstall( savedObjectsClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi | null + alertingRulesClient: RulesClientApi ) { const installingPackages = await getPackageSavedObjects(savedObjectsClient, { searchFields: ['install_status'], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts index d90587c809bfa..dfd6cce6b91bc 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.test.ts @@ -67,7 +67,6 @@ function sleep(millis: number) { describe('_stateMachineInstallPackage', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; beforeEach(async () => { soClient = savedObjectsClientMock.create(); @@ -83,10 +82,6 @@ describe('_stateMachineInstallPackage', () => { jest.mocked(saveArchiveEntriesFromAssetsMap).mockResolvedValue({ saved_objects: [], }); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(() => { @@ -114,7 +109,6 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -177,7 +171,6 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -214,7 +207,6 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -264,7 +256,6 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -332,7 +323,6 @@ describe('_stateMachineInstallPackage', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { packageInfo: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts index 375f220e8e066..bc4c72cdf38ca 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts @@ -62,7 +62,7 @@ import { handleState } from './state_machine'; export interface InstallContext extends StateContext { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; esClient: ElasticsearchClient; logger: Logger; installedPkg?: SavedObject; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts index d3bc4dce9d22c..6cec95cd7c53c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_create_restart_installation.test.ts @@ -46,7 +46,6 @@ const mockedAuditLoggingService = auditLoggingService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); describe('When package is stuck in `installing`', () => { @@ -72,10 +71,6 @@ describe('stepCreateRestartInstallation', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(() => { mockedAuditLoggingService.writeCustomSoAuditLog.mockReset(); @@ -88,7 +83,6 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -125,7 +119,6 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -170,7 +163,6 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -215,7 +207,6 @@ describe('stepCreateRestartInstallation', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts index 2e1e3e7054a75..06201770ee2e2 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_delete_previous_pipelines.test.ts @@ -40,8 +40,6 @@ const mockedIsTopLevelPipeline = isTopLevelPipeline as jest.MockedFunction< describe('stepDeletePreviousPipelines', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; - const getMockInstalledPackageSo = ( installedEs: EsAssetReference[] = [] ): SavedObject => { @@ -67,10 +65,6 @@ describe('stepDeletePreviousPipelines', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedDeletePreviousPipelines).mockReset(); @@ -137,7 +131,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -184,7 +177,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -231,7 +223,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -325,7 +316,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'update', @@ -356,7 +346,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'reupdate', @@ -387,7 +376,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'rollback', @@ -428,7 +416,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { ...packageInstallContext, paths: ['some/path/1', 'some/path/2'] }, installType: 'install', @@ -470,7 +457,6 @@ describe('stepDeletePreviousPipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { ...packageInstallContext, paths: ['some/path/1', 'some/path/2'] }, installType: 'update', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts index b03b41ea01dd1..7b78b7967abc7 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_ilm_policies.test.ts @@ -63,7 +63,6 @@ const packageInstallContext = { }; let soClient: jest.Mocked; let esClient: jest.Mocked; -let alertingRulesClient: any; describe('stepInstallILMPolicies', () => { const mockInstalledPackageSo: SavedObject = { @@ -96,10 +95,6 @@ describe('stepInstallILMPolicies', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(installILMPolicy).mockReset(); @@ -127,7 +122,6 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -160,7 +154,6 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -234,7 +227,6 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { packageInfo: { @@ -330,7 +322,6 @@ describe('stepInstallILMPolicies', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -456,7 +447,6 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -515,7 +505,6 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -544,7 +533,6 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -571,7 +559,6 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -599,7 +586,6 @@ describe('cleanupILMPoliciesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts index e534fb0d64bdc..1c368cfd998d3 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_index_template_pipelines.test.ts @@ -49,7 +49,6 @@ const mockedInstallIndexTemplatesAndPipelines = >; let soClient: jest.Mocked; let esClient: jest.Mocked; -let alertingRulesClient: any; describe('stepInstallIndexTemplatePipelines', () => { const getMockInstalledPackageSo = ( @@ -77,10 +76,6 @@ describe('stepInstallIndexTemplatePipelines', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedInstallIndexTemplatesAndPipelines).mockReset(); @@ -165,7 +160,6 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -330,7 +324,6 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -478,7 +471,6 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -558,7 +550,6 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -613,7 +604,6 @@ describe('stepInstallIndexTemplatePipelines', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install', @@ -724,7 +714,6 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -783,7 +772,6 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -812,7 +800,6 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -839,7 +826,6 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -867,7 +853,6 @@ describe('cleanupIndexTemplatePipelinesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts index 31054f4e6c96c..873fa86e5df74 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.test.ts @@ -59,7 +59,6 @@ const mockedDeleteKibanaAssets = deleteKibanaAssets as jest.MockedFunction< let soClient: jest.Mocked; let esClient: jest.Mocked; -let alertingRulesClient: any; const packageInstallContext = { packageInfo: { @@ -88,10 +87,6 @@ describe('stepInstallKibanaAssets', () => { soClient.get.mockImplementation(async (type, id) => { return { id, attributes: {} } as any; }); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; @@ -101,7 +96,6 @@ describe('stepInstallKibanaAssets', () => { const installationPromise = stepInstallKibanaAssets({ savedObjectsClient: soClient, esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -141,7 +135,6 @@ describe('stepInstallKibanaAssets', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -188,7 +181,6 @@ describe('stepInstallKibanaAssetsWithStreaming', () => { const result = await stepInstallKibanaAssetsWithStreaming({ savedObjectsClient: soClient, esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext: { archiveIterator, @@ -257,7 +249,6 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -289,7 +280,6 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -317,7 +307,6 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -343,7 +332,6 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -370,7 +358,6 @@ describe('cleanUpKibanaAssetsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -410,7 +397,6 @@ describe('cleanUpUnusedKibanaAssetsStep', () => { savedObjectsClient: soClient, savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installType: 'install' as const, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts index 389a5d3a566bc..df939f3a458b6 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_mlmodel.test.ts @@ -59,7 +59,6 @@ const packageInstallContext = { }; let soClient: jest.Mocked; let esClient: jest.Mocked; -let alertingRulesClient: any; describe('stepInstallMlModel', () => { const getMockInstalledPackageSo = ( @@ -87,10 +86,6 @@ describe('stepInstallMlModel', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedInstallMlModel).mockReset(); @@ -127,7 +122,6 @@ describe('stepInstallMlModel', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -157,7 +151,6 @@ describe('stepInstallMlModel', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -234,7 +227,6 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -293,7 +285,6 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -322,7 +313,6 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -349,7 +339,6 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -377,7 +366,6 @@ describe('cleanUpMlModelStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts index c561dc919a379..3bf07d52c6cbf 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_transforms.test.ts @@ -38,7 +38,6 @@ const mockCleanupTransforms = cleanupTransforms as jest.MockedFunction; let esClient: jest.Mocked; -let alertingRulesClient: any; const packageInstallContext = { packageInfo: { @@ -84,10 +83,6 @@ describe('stepInstallTransforms', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedInstallTransforms).mockReset(); @@ -127,7 +122,6 @@ describe('stepInstallTransforms', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -160,7 +154,6 @@ describe('stepInstallTransforms', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -236,7 +229,6 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -263,7 +255,6 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -291,7 +282,6 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -317,7 +307,6 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -344,7 +333,6 @@ describe('cleanupTransformsStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts index 2734f3a606170..7fa00a1c57f57 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_remove_legacy_templates.test.ts @@ -37,7 +37,6 @@ const mockedRemoveLegacyTemplates = removeLegacyTemplates as jest.MockedFunction describe('stepRemoveLegacyTemplates', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); const getMockInstalledPackageSo = ( @@ -65,10 +64,6 @@ describe('stepRemoveLegacyTemplates', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedRemoveLegacyTemplates).mockReset(); @@ -121,7 +116,6 @@ describe('stepRemoveLegacyTemplates', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext, installedPkg, @@ -145,7 +139,6 @@ describe('stepRemoveLegacyTemplates', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext, installedPkg, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts index 7ee954cc5e9fb..26a4f17132357 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_archive_entries.test.ts @@ -41,7 +41,6 @@ const mockedRemoveArchiveEntries = removeArchiveEntries as jest.MockedFunction< >; let soClient: jest.Mocked; let esClient: jest.Mocked; -let alertingRulesClient: any; const assetsMap = new Map([ [ @@ -112,10 +111,6 @@ describe('stepSaveArchiveEntries', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedSaveArchiveEntriesFromAssetsMap).mockReset(); @@ -154,7 +149,6 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -198,7 +192,6 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -248,7 +241,6 @@ describe('stepSaveArchiveEntries', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -322,7 +314,6 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -351,7 +342,6 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -378,7 +368,6 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -403,7 +392,6 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { @@ -429,7 +417,6 @@ describe('cleanupArchiveEntriesStep', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg: { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts index 52718eb576512..49b1ee84d88c5 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_save_system_object.test.ts @@ -32,17 +32,12 @@ const mockedPackagePolicyService = packagePolicyService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); beforeEach(async () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(() => { @@ -69,7 +64,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -137,7 +131,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts index 1f07c6b02ec46..017805d34efef 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_update_current_write_indices.test.ts @@ -43,8 +43,6 @@ const createMockTemplate = ({ name, composedOf = [] }: { name: string; composedO describe('stepUpdateCurrentWriteIndices', () => { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; - const getMockInstalledPackageSo = ( installedEs: EsAssetReference[] = [] ): SavedObject => { @@ -70,10 +68,6 @@ describe('stepUpdateCurrentWriteIndices', () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(async () => { jest.mocked(mockedUpdateCurrentWriteIndices).mockReset(); @@ -126,7 +120,6 @@ describe('stepUpdateCurrentWriteIndices', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, @@ -151,7 +144,6 @@ describe('stepUpdateCurrentWriteIndices', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger: loggerMock.create(), packageInstallContext, installedPkg, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts index 1ec783abd754d..887ae21cd5e2a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/update_latest_executed_state.test.ts @@ -42,17 +42,12 @@ const mockedAuditLoggingService = auditLoggingService as jest.Mocked { let soClient: jest.Mocked; let esClient: jest.Mocked; - let alertingRulesClient: any; const logger = loggingSystemMock.createLogger(); beforeEach(async () => { soClient = savedObjectsClientMock.create(); esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; appContextService.start(createAppContextStartContractMock()); - alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); afterEach(() => { mockedAuditLoggingService.writeCustomSoAuditLog.mockReset(); @@ -65,7 +60,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -122,7 +116,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -160,7 +153,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), @@ -206,7 +198,6 @@ describe('updateLatestExecutedState', () => { // @ts-ignore savedObjectsImporter: jest.fn(), esClient, - alertingRulesClient, logger, packageInstallContext: { archiveIterator: createArchiveIteratorFromMap(new Map()), diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts index 2e5459492bbb2..0ac71cc7c5a84 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.test.ts @@ -18,10 +18,6 @@ jest.mock('./bundled_packages'); const mockedInstallPackage = jest.mocked(installPackage); const mockedGetBundledPackageForInstallation = jest.mocked(getBundledPackageForInstallation); -const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), -} as any; describe('reinstallPackageForInstallation', () => { beforeEach(() => { @@ -39,7 +35,6 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient, installation: { install_source: 'upload', } as Installation, @@ -54,7 +49,6 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient, installation: { install_source: 'registry', name: 'test', @@ -79,7 +73,6 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient, installation: { install_source: 'bundled', name: 'test_bundled', @@ -105,7 +98,6 @@ describe('reinstallPackageForInstallation', () => { reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient, installation: { install_source: 'upload', name: 'test_bundled', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts index de6b98a49a5e9..cb2b91de252f7 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/reinstall.ts @@ -7,7 +7,6 @@ import type { ElasticsearchClient, SavedObjectsClientContract } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import type { Installation } from '../../../types'; import { pkgToPkgKey } from '../registry'; @@ -21,12 +20,10 @@ import { installPackage } from './install'; export async function reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient, installation, }: { soClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi | null; installation: Installation; }) { if (installation.install_source === 'upload' || installation.install_source === 'bundled') { @@ -47,7 +44,6 @@ export async function reinstallPackageForInstallation({ // If the package is bundled reinstall from the registry will still use the bundled package. installSource: 'registry', savedObjectsClient: soClient, - alertingRulesClient, pkgkey: pkgToPkgKey({ name: installation.name, version: installation.version, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 605b885878532..8dd71e10b195a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -60,7 +60,7 @@ const MAX_ASSETS_TO_DELETE = 1000; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; pkgName: string; pkgVersion?: string; esClient: ElasticsearchClient; @@ -151,7 +151,7 @@ export async function deleteKibanaAssets({ spaceId = DEFAULT_SPACE_ID, }: { installedObjects: KibanaAssetReference[]; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; logger: Logger; packageSpecConditions?: PackageSpecConditions; spaceId?: string; @@ -178,19 +178,10 @@ export async function deleteKibanaAssets({ (installedObject) => installedObject.type === KibanaSavedObjectType.alert ); - if (alertAssets.length > 0 && !alertingRulesClient) { - logger.debug( - 'Deleting alert rules will be skipped because no alert rules client was provided. This maybe due to the operation running outside of a request context.' - ); - } - if (minKibana && minKibana.major >= 8) { - const deleteAlertRulesPromise = alertingRulesClient - ? bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger) - : Promise.resolve(); await Promise.all([ bulkDeleteSavedObjects(soAssets, namespace, savedObjectsClient, logger), - deleteAlertRulesPromise, + bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger), ]); } else { const { resolved_objects: resolvedObjects } = await savedObjectsClient.bulkResolve( @@ -384,7 +375,7 @@ export async function deletePrerequisiteAssets( async function deleteAssets( savedObjectsClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi | null, + alertingRulesClient: RulesClientApi, { installed_es: installedEs, installed_kibana: installedKibana, @@ -475,7 +466,7 @@ export async function deleteKibanaSavedObjectsAssets({ spaceId, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi | null; + alertingRulesClient: RulesClientApi; installedPkg: SavedObject; spaceId?: string; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts index 500e6fbabcac9..46911e8c8a85c 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.test.ts @@ -39,10 +39,6 @@ describe('updateCustomIntegration', () => { let mockContract: ReturnType; const savedObjectsClient = savedObjectsClientMock.create(); const esClient = elasticsearchClientMock.createElasticsearchClient(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; beforeEach(() => { mockContract = createAppContextStartContractMock(); @@ -108,16 +104,10 @@ describe('updateCustomIntegration', () => { }); it('should update custom integration with new version and readme', async () => { - const result = await updateCustomIntegration( - esClient, - savedObjectsClient, - alertingRulesClient, - 'test-integration', - { - readMeData: '# Updated Test Integration', - categories: ['custom'], - } - ); + const result = await updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { + readMeData: '# Updated Test Integration', + categories: ['custom'], + }); // Verify the updated version expect(result).toEqual({ @@ -147,7 +137,6 @@ describe('updateCustomIntegration', () => { const result = await incrementVersionAndUpdate( savedObjectsClient, esClient, - alertingRulesClient, 'test-integration', { readme: '# Updated Test Integration', @@ -175,15 +164,9 @@ describe('updateCustomIntegration', () => { }); await expect( - updateCustomIntegration( - esClient, - savedObjectsClient, - alertingRulesClient, - 'non-existent-integration', - { - readMeData: '# Updated Test Integration', - } - ) + updateCustomIntegration(esClient, savedObjectsClient, 'non-existent-integration', { + readMeData: '# Updated Test Integration', + }) ).rejects.toThrow('Integration with ID non-existent-integration not found'); }); @@ -192,15 +175,9 @@ describe('updateCustomIntegration', () => { mockGetInstalledPackageWithAssets.mockRejectedValueOnce(testError); await expect( - updateCustomIntegration( - esClient, - savedObjectsClient, - alertingRulesClient, - 'test-integration', - { - readMeData: '# Updated Test Integration', - } - ) + updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { + readMeData: '# Updated Test Integration', + }) ).rejects.toThrow('Test error during update'); }); @@ -219,15 +196,9 @@ describe('updateCustomIntegration', () => { }); await expect( - updateCustomIntegration( - esClient, - savedObjectsClient, - alertingRulesClient, - 'test-integration', - { - readMeData: '# Updated Test Integration', - } - ) + updateCustomIntegration(esClient, savedObjectsClient, 'test-integration', { + readMeData: '# Updated Test Integration', + }) ).rejects.toThrow('Integration with ID test-integration is not a custom integration'); }); }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts index 80f58ac410efc..a53fdd1294fda 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/update_custom_integration.ts @@ -10,7 +10,6 @@ import type { SavedObjectsClientContract, } from '@kbn/core/server'; import { load, dump } from 'js-yaml'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { PACKAGES_SAVED_OBJECT_TYPE, @@ -41,7 +40,6 @@ import { installPackageWithStateMachine } from './install'; export async function updateCustomIntegration( esClient: ElasticsearchClient, soClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, id: string, fields: { readMeData?: string; @@ -72,7 +70,7 @@ export async function updateCustomIntegration( newVersion[2] = (parseInt(newVersion[2], 10) + 1).toString(); const newVersionString = newVersion.join('.'); // Increment the version of everything and create a new package - const res = await incrementVersionAndUpdate(soClient, esClient, alertingRulesClient, id, { + const res = await incrementVersionAndUpdate(soClient, esClient, id, { version: newVersionString, readme: fields.readMeData, categories: fields.categories, @@ -86,7 +84,6 @@ export async function updateCustomIntegration( export async function incrementVersionAndUpdate( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, pkgName: string, data: { version: string; @@ -176,7 +173,6 @@ export async function incrementVersionAndUpdate( installType: 'install', savedObjectsClient: soClient, esClient, - alertingRulesClient, spaceId: 'default', force: true, paths: packageInstallContext.paths, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts index d130f1bda1fa6..12f1abf0dfa7e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.test.ts @@ -273,10 +273,6 @@ describe('Package policy service', () => { it('should call audit logger', async () => { const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const soClient = createSavedObjectClientMock(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; soClient.create.mockResolvedValueOnce({ id: 'test-package-policy', @@ -290,7 +286,6 @@ describe('Package policy service', () => { await packagePolicyService.create( soClient, esClient, - alertingRulesClient, { name: 'Test Package Policy', namespace: 'test', @@ -321,10 +316,6 @@ describe('Package policy service', () => { const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const soClient = createSavedObjectClientMock(); - const alertingRulesClient = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - } as any; soClient.create.mockResolvedValueOnce({ id: 'test-package-policy', @@ -339,7 +330,6 @@ describe('Package policy service', () => { packagePolicyService.create( soClient, esClient, - alertingRulesClient, { name: 'Test Package Policy', namespace: 'test', diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts index 1f6a43650356c..1c31f409f7608 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts @@ -71,7 +71,7 @@ export interface PackagePolicyClient { create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClientApi: RulesClientApi | null, + alertingRulesClientApi: RulesClientApi, packagePolicy: NewPackagePolicy, options?: { spaceId?: string; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts b/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts index e5b4aa720fd90..cf0ee7e70ca15 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/preconfiguration.ts @@ -99,7 +99,6 @@ export async function ensurePreconfiguredPackagesAndPolicies( savedObjectsClient: defaultSoClient, esClient, packagesToInstall, - alertingRulesClient: null, force: true, // Always force outdated packages to be installed if a later version isn't installed skipIfInstalled: true, // force flag alone would reinstall packages that are already installed spaceId, @@ -129,7 +128,7 @@ export async function ensurePreconfiguredPackagesAndPolicies( // will occur between upgrading the package and reinstalling the previously failed package. // By moving this outside of the Promise.all, the upgrade will occur first, and then we'll attempt to reinstall any // packages that are stuck in the installing state. - await ensurePackagesCompletedInstall(defaultSoClient, esClient, null); + await ensurePackagesCompletedInstall(defaultSoClient, esClient); // Create policies specified in Kibana config logger.debug(`Creating preconfigured policies`); @@ -189,7 +188,6 @@ export async function ensurePreconfiguredPackagesAndPolicies( const updatedPolicy = await agentPolicyService.update( namespacedSoClient, esClient, - null, String(preconfiguredAgentPolicy.id), newFields, { @@ -307,7 +305,6 @@ export async function ensurePreconfiguredPackagesAndPolicies( await agentPolicyService.update( namespacedSoClient, esClient, - null, policy!.id, { is_managed: true }, { @@ -399,7 +396,6 @@ async function addPreconfiguredPolicyPackages( await addPackageToAgentPolicy( namespacedSoClient, esClient, - null, agentPolicy, packageInfo, name, @@ -424,7 +420,7 @@ async function addPreconfiguredPolicyPackages( {} ); - await packagePolicyService.create(namespacedSoClient, esClient, null, newPackagePolicy, { + await packagePolicyService.create(namespacedSoClient, esClient, newPackagePolicy, { id, bumpRevision: bumpAgentPolicyRevison, skipEnsureInstalled: true, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/setup.ts b/x-pack/platform/plugins/shared/fleet/server/services/setup.ts index 34d12ba67c8f3..929abc9aa2df4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/setup.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/setup.ts @@ -332,7 +332,6 @@ export async function ensureFleetGlobalEsAssets( await reinstallPackageForInstallation({ soClient, esClient, - alertingRulesClient: null, installation, }).catch((err) => { apm.captureError(err); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts index 7fd5856dd1c0f..0e16f88101685 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts @@ -31,6 +31,7 @@ describe('syncIntegrationsOnRemote', () => { let packageClientMock: any; let loggerMock: any; let soClientMock: any; + let alertingRulesClientMock: any; beforeEach(() => { getIndicesMock = jest.fn(); @@ -63,6 +64,10 @@ describe('syncIntegrationsOnRemote', () => { soClientMock = { update: jest.fn(), }; + alertingRulesClientMock = { + create: jest.fn(), + bulkDeleteRules: jest.fn(), + }; }); it('should throw error if multiple synced integrations ccr indices exist', async () => { @@ -72,7 +77,14 @@ describe('syncIntegrationsOnRemote', () => { }); await expect( - syncIntegrationsOnRemote(esClientMock, soClientMock, {} as any, abortController, loggerMock) + syncIntegrationsOnRemote( + esClientMock, + soClientMock, + alertingRulesClientMock, + {} as any, + abortController, + loggerMock + ) ).rejects.toThrowError( 'Not supported to sync multiple indices with prefix fleet-synced-integrations-ccr-*' ); @@ -144,6 +156,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -172,6 +185,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -203,6 +217,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -245,6 +260,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -280,6 +296,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -312,6 +329,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -348,6 +366,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -372,6 +391,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -421,6 +441,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -466,6 +487,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -502,6 +524,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -538,6 +561,7 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, + alertingRulesClientMock, packageClientMock, abortController, loggerMock diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 598d98c7dca72..32b8efe1484e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -215,7 +215,6 @@ async function uninstallPackageIfInstalled( savedObjectsClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, - alertingRulesClient: null, esClient, force: false, }); From 74b4c1d6d1c6c4e4ea07e378fa868ca1e4dcb613 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:45:39 -0700 Subject: [PATCH 16/41] Revert "Revert providing alert rules client in sync integrations task" This reverts commit e9f260c23936e28f53275dbdf217cc08c4bb9272. --- .../tasks/sync_integrations/sync_integrations_on_remote.ts | 6 +++++- .../tasks/sync_integrations/sync_integrations_task.ts | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 32b8efe1484e8..953b38f100468 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -10,6 +10,7 @@ import type { Logger, SavedObjectsClientContract, } from '@kbn/core/server'; +import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import semverEq from 'semver/functions/eq'; import semverGte from 'semver/functions/gte'; @@ -190,6 +191,7 @@ async function installPackageIfNotInstalled( async function uninstallPackageIfInstalled( esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClient, + alertingRulesClient: RulesClientApi, pkg: { package_name: string; package_version: string }, logger: Logger ) { @@ -213,6 +215,7 @@ async function uninstallPackageIfInstalled( try { await removeInstallation({ savedObjectsClient, + alertingRulesClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, esClient, @@ -231,6 +234,7 @@ async function uninstallPackageIfInstalled( export const syncIntegrationsOnRemote = async ( esClient: ElasticsearchClient, soClient: SavedObjectsClient, + alertingRulesClient: RulesClientApi, packageClient: PackageClient, abortController: AbortController, logger: Logger @@ -266,7 +270,7 @@ export const syncIntegrationsOnRemote = async ( if (abortController.signal.aborted) { throw new Error('Task was aborted'); } - await uninstallPackageIfInstalled(esClient, soClient, pkg, logger); + await uninstallPackageIfInstalled(esClient, soClient, alertingRulesClient, pkg, logger); } await clearCustomAssetFailedAttempts(soClient, syncIntegrationsDoc); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts index 081b0fc121856..177557cc9e1da 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts @@ -139,7 +139,7 @@ export class SyncIntegrationsTask { } const fakeRequest = kibanaRequestFactory({ - headers: {}, + headers: { authorization: `ApiKey ${taskInstance.apiKey}` }, path: '/', route: { settings: {} }, url: { href: '', hash: '' } as URL, From 08f44e70a97929fa24be82d473dc799fbeea9e33 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:45:51 -0700 Subject: [PATCH 17/41] Revert "WIP: Add alert rules client dependency to callers in package policy service and tasks" This reverts commit e30bfaedf35a0de9e51b280085918e87e0123b37. --- .../server/services/epm/package_service.ts | 15 ++--------- .../fleet/server/services/package_policy.ts | 16 +----------- .../server/services/package_policy_service.ts | 4 +-- .../sync_integrations_on_remote.test.ts | 26 +------------------ .../sync_integrations_on_remote.ts | 6 +---- .../sync_integrations_task.ts | 19 ++------------ 6 files changed, 8 insertions(+), 78 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts index 7e3d29f78a3e8..8023c6da7b768 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/package_service.ts @@ -15,7 +15,7 @@ import type { } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; + import type { TypeOf } from '@kbn/config-schema'; import { HTTPAuthorizationHeader } from '../../../common/http_authorization_header'; @@ -161,7 +161,6 @@ export class PackageServiceImpl implements PackageService { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger ) {} @@ -186,7 +185,6 @@ export class PackageServiceImpl implements PackageService { return new PackageClientImpl( this.internalEsClient, this.internalSoClient, - this.alertingRulesClient, this.logger, preflightCheck, request @@ -194,12 +192,7 @@ export class PackageServiceImpl implements PackageService { } public get asInternalUser() { - return new PackageClientImpl( - this.internalEsClient, - this.internalSoClient, - this.alertingRulesClient, - this.logger - ); + return new PackageClientImpl(this.internalEsClient, this.internalSoClient, this.logger); } } @@ -209,7 +202,6 @@ class PackageClientImpl implements PackageClient { constructor( private readonly internalEsClient: ElasticsearchClient, private readonly internalSoClient: SavedObjectsClientContract, - private readonly alertingRulesClient: RulesClientApi, private readonly logger: Logger, private readonly preflightCheck?: ( requiredAuthz?: FleetAuthzRouteConfig['fleetAuthz'] @@ -247,7 +239,6 @@ class PackageClientImpl implements PackageClient { ...options, esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, }); } @@ -285,7 +276,6 @@ class PackageClientImpl implements PackageClient { installSource: 'registry', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, keepFailedInstallation, useStreaming, @@ -319,7 +309,6 @@ class PackageClientImpl implements PackageClient { installSource: 'custom', esClient: this.internalEsClient, savedObjectsClient: this.internalSoClient, - alertingRulesClient: this.alertingRulesClient, neverIgnoreVerificationError: !force, authorizationHeader: this.getAuthorizationHeader(), }); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts index dd9b9e5cf4f6e..58a878232158f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy.ts @@ -23,7 +23,6 @@ import type { } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { SavedObjectsUtils } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { v4 as uuidv4 } from 'uuid'; import { load } from 'js-yaml'; import semverGt from 'semver/functions/gt'; @@ -236,7 +235,6 @@ class PackagePolicyClientImpl implements PackagePolicyClient { public async create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, packagePolicy: NewPackagePolicy, options: { authorizationHeader?: HTTPAuthorizationHeader | null; @@ -365,7 +363,6 @@ class PackagePolicyClientImpl implements PackagePolicyClient { if (!options?.skipEnsureInstalled) { await ensureInstalledPackage({ esClient, - alertingRulesClient, spaceId: options?.spaceId || DEFAULT_SPACE_ID, savedObjectsClient: soClient, pkgName: enrichedPackagePolicy.package.name, @@ -2151,7 +2148,6 @@ class PackagePolicyClientImpl implements PackagePolicyClient { public async buildPackagePolicyFromPackage( soClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, pkgName: string, options?: { logger?: Logger; installMissingPackage?: boolean } ): Promise { @@ -2165,7 +2161,6 @@ class PackagePolicyClientImpl implements PackagePolicyClient { const esClient = await appContextService.getInternalUserESClient(); const result = await ensureInstalledPackage({ esClient, - alertingRulesClient, pkgName, savedObjectsClient: soClient, }); @@ -2653,7 +2648,6 @@ class PackagePolicyClientWithAuthz extends PackagePolicyClientImpl { async create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, packagePolicy: NewPackagePolicy, options?: { authorizationHeader?: HTTPAuthorizationHeader | null; @@ -2676,15 +2670,7 @@ class PackagePolicyClientWithAuthz extends PackagePolicyClientImpl { }, }); - return super.create( - soClient, - esClient, - alertingRulesClient, - packagePolicy, - options, - context, - request - ); + return super.create(soClient, esClient, packagePolicy, options, context, request); } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts index 1c31f409f7608..4b150f4e415f8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/package_policy_service.ts @@ -13,7 +13,7 @@ import type { ElasticsearchClient, SavedObjectsClientContract, } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; + import type { SavedObjectError } from '@kbn/core-saved-objects-common'; import type { HTTPAuthorizationHeader } from '../../common/http_authorization_header'; @@ -71,7 +71,6 @@ export interface PackagePolicyClient { create( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClientApi: RulesClientApi, packagePolicy: NewPackagePolicy, options?: { spaceId?: string; @@ -206,7 +205,6 @@ export interface PackagePolicyClient { buildPackagePolicyFromPackage( soClient: SavedObjectsClientContract, - alertingRulesClientApi: RulesClientApi, pkgName: string, options?: { logger?: Logger; installMissingPackage?: boolean } ): Promise; diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts index 0e16f88101685..7fd5856dd1c0f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.test.ts @@ -31,7 +31,6 @@ describe('syncIntegrationsOnRemote', () => { let packageClientMock: any; let loggerMock: any; let soClientMock: any; - let alertingRulesClientMock: any; beforeEach(() => { getIndicesMock = jest.fn(); @@ -64,10 +63,6 @@ describe('syncIntegrationsOnRemote', () => { soClientMock = { update: jest.fn(), }; - alertingRulesClientMock = { - create: jest.fn(), - bulkDeleteRules: jest.fn(), - }; }); it('should throw error if multiple synced integrations ccr indices exist', async () => { @@ -77,14 +72,7 @@ describe('syncIntegrationsOnRemote', () => { }); await expect( - syncIntegrationsOnRemote( - esClientMock, - soClientMock, - alertingRulesClientMock, - {} as any, - abortController, - loggerMock - ) + syncIntegrationsOnRemote(esClientMock, soClientMock, {} as any, abortController, loggerMock) ).rejects.toThrowError( 'Not supported to sync multiple indices with prefix fleet-synced-integrations-ccr-*' ); @@ -156,7 +144,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -185,7 +172,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -217,7 +203,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -260,7 +245,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -296,7 +280,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -329,7 +312,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -366,7 +348,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -391,7 +372,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -441,7 +421,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -487,7 +466,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -524,7 +502,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock @@ -561,7 +538,6 @@ describe('syncIntegrationsOnRemote', () => { await syncIntegrationsOnRemote( esClientMock, soClientMock, - alertingRulesClientMock, packageClientMock, abortController, loggerMock diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts index 953b38f100468..32b8efe1484e8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_on_remote.ts @@ -10,7 +10,6 @@ import type { Logger, SavedObjectsClientContract, } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import semverEq from 'semver/functions/eq'; import semverGte from 'semver/functions/gte'; @@ -191,7 +190,6 @@ async function installPackageIfNotInstalled( async function uninstallPackageIfInstalled( esClient: ElasticsearchClient, savedObjectsClient: SavedObjectsClient, - alertingRulesClient: RulesClientApi, pkg: { package_name: string; package_version: string }, logger: Logger ) { @@ -215,7 +213,6 @@ async function uninstallPackageIfInstalled( try { await removeInstallation({ savedObjectsClient, - alertingRulesClient, pkgName: pkg.package_name, pkgVersion: pkg.package_version, esClient, @@ -234,7 +231,6 @@ async function uninstallPackageIfInstalled( export const syncIntegrationsOnRemote = async ( esClient: ElasticsearchClient, soClient: SavedObjectsClient, - alertingRulesClient: RulesClientApi, packageClient: PackageClient, abortController: AbortController, logger: Logger @@ -270,7 +266,7 @@ export const syncIntegrationsOnRemote = async ( if (abortController.signal.aborted) { throw new Error('Task was aborted'); } - await uninstallPackageIfInstalled(esClient, soClient, alertingRulesClient, pkg, logger); + await uninstallPackageIfInstalled(esClient, soClient, pkg, logger); } await clearCustomAssetFailedAttempts(soClient, syncIntegrationsDoc); diff --git a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts index 177557cc9e1da..4d15e1b1658d4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts +++ b/x-pack/platform/plugins/shared/fleet/server/tasks/sync_integrations/sync_integrations_task.ts @@ -7,17 +7,14 @@ import { keyBy } from 'lodash'; import { SavedObjectsClient } from '@kbn/core/server'; import type { CoreSetup, ElasticsearchClient, Logger } from '@kbn/core/server'; -import { kibanaRequestFactory } from '@kbn/core-http-server-utils'; import type { ConcreteTaskInstance, - RunContext, TaskManagerSetupContract, TaskManagerStartContract, } from '@kbn/task-manager-plugin/server'; import { getDeleteTaskRunResult } from '@kbn/task-manager-plugin/server/task'; import type { LoggerFactory } from '@kbn/core/server'; import { errors } from '@elastic/elasticsearch'; -import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common'; import { SO_SEARCH_LIMIT, outputType } from '../../../common/constants'; import type { NewRemoteElasticsearchOutput } from '../../../common/types'; @@ -71,7 +68,7 @@ export class SyncIntegrationsTask { [TYPE]: { title: TITLE, timeout: TIMEOUT, - createTaskRunner: ({ taskInstance }: RunContext) => { + createTaskRunner: ({ taskInstance }: { taskInstance: ConcreteTaskInstance }) => { return { run: async () => { return this.runTask(taskInstance, core); @@ -138,20 +135,9 @@ export class SyncIntegrationsTask { return; } - const fakeRequest = kibanaRequestFactory({ - headers: { authorization: `ApiKey ${taskInstance.apiKey}` }, - path: '/', - route: { settings: {} }, - url: { href: '', hash: '' } as URL, - raw: { req: { url: '/' } } as any, - }); - - core.http.basePath.set(fakeRequest, DEFAULT_SPACE_ID); - - const [coreStart, startDeps, { packageService }] = (await core.getStartServices()) as any; + const [coreStart, _startDeps, { packageService }] = (await core.getStartServices()) as any; const esClient = coreStart.elasticsearch.client.asInternalUser; const soClient = new SavedObjectsClient(coreStart.savedObjects.createInternalRepository()); - const alertingRulesClient = startDeps.alerting.getRulesClientWithRequest(fakeRequest); try { // write integrations on main cluster @@ -161,7 +147,6 @@ export class SyncIntegrationsTask { await syncIntegrationsOnRemote( esClient, soClient, - alertingRulesClient, packageService.asInternalUser, this.abortController, this.logger From b5615b21bc9ab62bd30bc80681346348becf6c88 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:12 -0700 Subject: [PATCH 18/41] Revert "Fix unit tests" This reverts commit 053dd9c4675e7e8a90f11f539d8b38bce087a21b. --- .../server/services/epm/packages/remove.test.ts | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts index 7c73f6fb7a3ac..fcccb1fd6a6be 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.test.ts @@ -47,7 +47,6 @@ const mockPackagePolicyService = packagePolicyService as jest.Mocked { let soClientMock: any; const esClientMock = {} as any; - let alertingRulesClientMock: any; beforeEach(() => { soClientMock = { get: jest.fn().mockResolvedValue({ attributes: { installed_kibana: [], installed_es: [] } }), @@ -56,9 +55,6 @@ describe('removeInstallation', () => { find: jest.fn().mockResolvedValue({ saved_objects: [] }), bulkResolve: jest.fn().mockResolvedValue({ resolved_objects: [] }), } as any; - alertingRulesClientMock = { - bulkDeleteRules: jest.fn().mockResolvedValue({}), - }; }); it('should remove package policies when force', async () => { await removeInstallation({ @@ -66,7 +62,6 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, - alertingRulesClient: alertingRulesClientMock, force: true, }); expect(mockPackagePolicyService.delete).toHaveBeenCalledWith( @@ -84,7 +79,6 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, - alertingRulesClient: alertingRulesClientMock, force: false, }) ).rejects.toThrowError( @@ -98,7 +92,6 @@ describe('removeInstallation', () => { pkgName: 'elastic_agent', pkgVersion: '1.0.0', esClient: esClientMock, - alertingRulesClient: alertingRulesClientMock, force: false, }); expect(mockPackagePolicyService.delete).toHaveBeenCalledTimes(2); @@ -110,7 +103,6 @@ describe('removeInstallation', () => { pkgName: 'system', pkgVersion: '1.0.0', esClient: esClientMock, - alertingRulesClient: alertingRulesClientMock, force: true, }); @@ -156,7 +148,6 @@ describe('deleteESAsset', () => { describe('cleanupAssets', () => { let soClientMock: any; const esClientMock = {} as any; - let alertingRulesClientMock: any; beforeEach(() => { soClientMock = { get: jest @@ -174,9 +165,6 @@ describe('deleteESAsset', () => { find: jest.fn().mockResolvedValue({ saved_objects: [] }), bulkResolve: jest.fn().mockResolvedValue({ resolved_objects: [] }), } as any; - alertingRulesClientMock = { - bulkDeleteRules: jest.fn().mockResolvedValue({}), - }; }); it('should remove assets marked for deletion', async () => { @@ -228,7 +216,6 @@ describe('deleteESAsset', () => { installationToDelete, installation, esClientMock, - alertingRulesClientMock, soClientMock ); From 2fe4db18d47077d5e7e43f20774f040bd6ecd40a Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:18 -0700 Subject: [PATCH 19/41] Revert "Support alert rules in streaming package install" This reverts commit 8a44dfafecb641965aedefe101dcf4e5fd61753b. --- .../services/epm/kibana/assets/install.ts | 43 +++++++------- .../kibana/assets/install_with_streaming.ts | 59 ++++--------------- .../steps/step_install_kibana_assets.ts | 17 +----- .../server/services/epm/packages/remove.ts | 4 +- 4 files changed, 39 insertions(+), 84 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 1b0b5d2377304..4985d0e5b2c97 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -62,7 +62,7 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; -export type SavedObjectAsset = Pick< +type SavedObjectAsset = Pick< SavedObject, | 'id' | 'attributes' @@ -166,6 +166,25 @@ export async function installKibanaAssets(options: { }) ); + interface InstallGroups { + asSavedObjects: SavedObjectAsset[]; + asAlertRules: AlertRuleAsset[]; + } + const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { + return assetEntries.reduce( + (installGroups, assetEntry) => { + if (assetEntry.assetType === KibanaAssetType.alert) { + installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; + return installGroups; + } + + installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; + return installGroups; + }, + { asSavedObjects: [], asAlertRules: [] } + ); + }; + async function flushAssetsToInstall() { await installManagedIndexPatternOnce(); @@ -648,7 +667,7 @@ function removeReservedIndexPatterns(kibanaAssets: ArchiveAssetEntry[]) { return kibanaAssets.filter((assetEntry) => !reservedPatterns.includes(assetEntry.asset.id)); } -export function toAssetReference({ id, type }: ArchiveAsset) { +export function toAssetReference({ id, type }: SavedObject) { const reference: AssetReference = { id, type: type as KibanaSavedObjectType }; return reference; @@ -657,23 +676,3 @@ export function toAssetReference({ id, type }: ArchiveAsset) { function hasReferences(assetsToInstall: SavedObjectAsset[]) { return assetsToInstall.some((asset) => asset.references.length); } - -interface InstallGroups { - asSavedObjects: SavedObjectAsset[]; - asAlertRules: AlertRuleAsset[]; -} - -export function createInstallGroups(assetEntries: ArchiveAssetEntry[]) { - return assetEntries.reduce( - (installGroups, assetEntry) => { - if (assetEntry.assetType === KibanaAssetType.alert) { - installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; - return installGroups; - } - - installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; - return installGroups; - }, - { asSavedObjects: [], asAlertRules: [] } - ); -} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index f24e2107a022a..2941fbb78bc8a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -5,17 +5,16 @@ * 2.0. */ -import type { SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import type { SavedObjectsClientContract } from '@kbn/core/server'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; -import { MAX_CONCURRENT_PACKAGE_ASSETS } from '../../../../constants'; import type { PackageInstallContext } from '../../../../../common/types'; -import { type KibanaAssetReference, KibanaAssetType } from '../../../../types'; +import type { KibanaAssetReference, KibanaAssetType } from '../../../../types'; import { getPathParts } from '../../archive'; import { saveKibanaAssetsRefs } from '../../packages/install'; -import type { ArchiveAsset, SavedObjectAsset } from './install'; +import type { ArchiveAsset } from './install'; import { KibanaSavedObjectTypeMapping, createSavedObjectKibanaAsset, @@ -24,24 +23,20 @@ import { toAssetReference, } from './install'; import { getSpaceAwareSaveobjectsClients } from './saved_objects'; -import { installAlertRules, type AlertRuleAsset } from './alert_rules'; interface InstallKibanaAssetsWithStreamingArgs { - logger: Logger; pkgName: string; packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; export async function installKibanaAssetsWithStreaming({ - logger, spaceId, packageInstallContext, - alertingRulesClient, savedObjectsClient, pkgName, }: InstallKibanaAssetsWithStreamingArgs): Promise { @@ -55,10 +50,8 @@ export async function installKibanaAssetsWithStreaming({ savedObjectsClient, }); - const assetTags = packageInstallContext.packageInfo?.asset_tags; const assetRefs: KibanaAssetReference[] = []; - let savedObjectBatch: SavedObjectAsset[] = []; - let alertRuleBatch: AlertRuleAsset[] = []; + let batch: ArchiveAsset[] = []; await archiveIterator.traverseEntries(async ({ path, buffer }) => { if (!buffer || !isKibanaAssetType(path)) { @@ -71,55 +64,29 @@ export async function installKibanaAssetsWithStreaming({ return; } - if (assetType === KibanaAssetType.alert) { - alertRuleBatch.push(savedObject as AlertRuleAsset); - } else { - savedObjectBatch.push(savedObject as SavedObjectAsset); - } - + batch.push(savedObject); assetRefs.push(toAssetReference(savedObject)); - if (savedObjectBatch.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { + if (batch.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, - kibanaAssets: savedObjectBatch, + kibanaAssets: batch, refresh: false, }); - savedObjectBatch = []; + batch = []; } }); - if (alertRuleBatch.length >= MAX_CONCURRENT_PACKAGE_ASSETS) { - await installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets: alertRuleBatch, - assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, - context: { pkgName, spaceId, assetTags }, - }); - alertRuleBatch = []; - } - // install any remaining assets - if (savedObjectBatch.length) { + if (batch.length) { await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, - kibanaAssets: savedObjectBatch, + kibanaAssets: batch, // Use wait_for with the last batch to ensure all assets are readable once the install is complete refresh: 'wait_for', }); } - if (alertRuleBatch.length) { - await installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets: alertRuleBatch, - assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, - context: { pkgName, spaceId, assetTags }, - }); - } - // Update the installation saved object with installed kibana assets await saveKibanaAssetsRefs(savedObjectsClient, pkgName, assetRefs); @@ -131,7 +98,7 @@ async function bulkCreateSavedObjects({ kibanaAssets, refresh, }: { - kibanaAssets: SavedObjectAsset[]; + kibanaAssets: ArchiveAsset[]; savedObjectsClient: SavedObjectsClientContract; refresh?: boolean | 'wait_for'; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts index 3068d1c70e6a8..0eb7c137fbd33 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts @@ -48,8 +48,7 @@ export async function stepInstallKibanaAssets(context: InstallContext) { } export async function stepInstallKibanaAssetsWithStreaming(context: InstallContext) { - const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId, logger } = - context; + const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId } = context; const { packageInfo } = packageInstallContext; const { name: pkgName } = packageInfo; @@ -62,7 +61,6 @@ export async function stepInstallKibanaAssetsWithStreaming(context: InstallConte pkgName, packageInstallContext, spaceId, - logger, }) ); @@ -73,7 +71,6 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { const { logger, installedPkg, - alertingRulesClient, packageInstallContext, spaceId, retryFromLastState, @@ -96,7 +93,6 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { await withPackageSpan('Retry transition - clean up Kibana assets first', async () => { await deleteKibanaAssets({ installedObjects, - alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, @@ -116,14 +112,8 @@ export async function cleanUpKibanaAssetsStep(context: InstallContext) { * */ export async function cleanUpUnusedKibanaAssetsStep(context: InstallContext) { - const { - logger, - installedPkg, - packageInstallContext, - spaceId, - installedKibanaAssetsRefs, - alertingRulesClient, - } = context; + const { logger, installedPkg, packageInstallContext, spaceId, installedKibanaAssetsRefs } = + context; const { packageInfo } = packageInstallContext; if (!installedKibanaAssetsRefs) { @@ -150,7 +140,6 @@ export async function cleanUpUnusedKibanaAssetsStep(context: InstallContext) { await withPackageSpan('Clean up Kibana assets that are no longer in the package', async () => { await deleteKibanaAssets({ installedObjects: assetsToRemove, - alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 8dd71e10b195a..18826d970a1b8 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -28,7 +28,7 @@ import { SO_SEARCH_LIMIT, USER_SETTINGS_TEMPLATE_SUFFIX, } from '../../../constants'; -import { ElasticsearchAssetType, KibanaSavedObjectType } from '../../../types'; +import { ElasticsearchAssetType } from '../../../types'; import type { AssetReference, AssetType, @@ -175,7 +175,7 @@ export async function deleteKibanaAssets({ // which might create high memory pressure if a package has a lot of assets. const [alertAssets, soAssets] = partition( installedObjects, - (installedObject) => installedObject.type === KibanaSavedObjectType.alert + (installedObject) => installedObject.type === 'alert' ); if (minKibana && minKibana.major >= 8) { From 1993549428916768273ef0590a793e2bd0ed1f5c Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:23 -0700 Subject: [PATCH 20/41] Revert "Support bulk uninstall of alert rules" This reverts commit bb2057e8db5495075de76bcb8bc65ca58d799de6. --- .../fleet/server/routes/epm/handlers.ts | 4 -- .../services/epm/kibana/assets/alert_rules.ts | 8 +-- .../services/epm/kibana/assets/install.ts | 24 +++------ .../server/services/epm/packages/install.ts | 24 ++++----- .../_state_machine_package_install.ts | 2 - .../server/services/epm/packages/remove.ts | 54 +++---------------- 6 files changed, 25 insertions(+), 91 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts index 7047964671b41..979e694fa5657 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts @@ -540,12 +540,8 @@ export const deletePackageHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const res = await removeInstallation({ savedObjectsClient, - alertingRulesClient, pkgName, pkgVersion, esClient, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index fe5e8c9e381b6..2a940baca8618 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -7,7 +7,7 @@ import { chunk } from 'lodash'; import type { Logger } from '@kbn/core/server'; import type { TypeOf } from '@kbn/config-schema'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import { KibanaSavedObjectType, type PackageSpecTags } from '../../../../types'; @@ -33,7 +33,7 @@ interface InstallAlertRulesParamsContext { interface InstallAlertRulesParams { logger: Logger; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; context: InstallAlertRulesParamsContext; assetsChunkSize?: number; @@ -91,7 +91,7 @@ async function installAlertRuleChunk({ context, }: { logger: Logger; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; context: InstallAlertRulesParamsContext; }) { @@ -109,7 +109,7 @@ async function installAlertRule({ context, }: { logger: Logger; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; alertRuleAsset: AlertRuleAsset; context: InstallAlertRulesParamsContext; }) { diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 4985d0e5b2c97..6d2fe50eacc77 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,7 +16,7 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -138,7 +138,7 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; spaceId: string; @@ -270,7 +270,7 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -341,7 +341,7 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -357,12 +357,7 @@ export async function installKibanaAssetsAndReferences({ const kibanaAssetsArchiveIterator = getKibanaAssetsArchiveIterator(packageInstallContext); if (installedPkg) { - await deleteKibanaSavedObjectsAssets({ - savedObjectsClient, - alertingRulesClient, - installedPkg, - spaceId, - }); + await deleteKibanaSavedObjectsAssets({ savedObjectsClient, installedPkg, spaceId }); } let installedKibanaAssetsRefs: KibanaAssetReference[] = []; @@ -410,14 +405,12 @@ export async function installKibanaAssetsAndReferences({ export async function deleteKibanaAssetsAndReferencesForSpace({ savedObjectsClient, - alertingRulesClient, logger, pkgName, installedPkg, spaceId, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; logger: Logger; pkgName: string; installedPkg: SavedObject; @@ -432,12 +425,7 @@ export async function deleteKibanaAssetsAndReferencesForSpace({ 'Impossible to delete kibana assets from the space where the package was installed, you must uninstall the package.' ); } - await deleteKibanaSavedObjectsAssets({ - savedObjectsClient, - alertingRulesClient, - installedPkg, - spaceId, - }); + await deleteKibanaSavedObjectsAssets({ savedObjectsClient, installedPkg, spaceId }); await saveKibanaAssetsRefs(savedObjectsClient, pkgName, null, true); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index d96aed266e310..da0d45801b9ee 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -21,7 +21,7 @@ import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import pRetry from 'p-retry'; import type { LicenseType } from '@kbn/licensing-plugin/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; +import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { KibanaAssetReference, @@ -175,7 +175,7 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -285,7 +285,7 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -327,13 +327,7 @@ export async function handleInstallPackageFailure({ if (keepFailedInstallation) { return; } - await removeInstallation({ - savedObjectsClient, - alertingRulesClient, - pkgName, - pkgVersion, - esClient, - }); + await removeInstallation({ savedObjectsClient, pkgName, pkgVersion, esClient }); return; } @@ -408,7 +402,7 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -432,7 +426,7 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -441,7 +435,7 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -625,7 +619,7 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClientApi; + alertingRulesClient: RulesClient; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -1341,7 +1335,7 @@ export const saveKibanaAssetsRefs = async ( export async function ensurePackagesCompletedInstall( savedObjectsClient: SavedObjectsClientContract, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi + alertingRulesClient: RulesClient ) { const installingPackages = await getPackageSavedObjects(savedObjectsClient, { searchFields: ['install_status'], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts index bc4c72cdf38ca..c941b6d60d63b 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/_state_machine_package_install.ts @@ -11,7 +11,6 @@ import type { SavedObjectsClientContract, } from '@kbn/core/server'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { PackageSavedObjectConflictError } from '../../../../errors'; @@ -62,7 +61,6 @@ import { handleState } from './state_machine'; export interface InstallContext extends StateContext { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; esClient: ElasticsearchClient; logger: Logger; installedPkg?: SavedObject; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 18826d970a1b8..18b5fe75d9961 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -6,11 +6,11 @@ */ import type { ElasticsearchClient, SavedObjectsClientContract, Logger } from '@kbn/core/server'; -import { differenceBy, chunk, partition } from 'lodash'; +import { differenceBy, chunk } from 'lodash'; import type { SavedObject } from '@kbn/core/server'; + import { SavedObjectsClient } from '@kbn/core/server'; -import type { RulesClientApi } from '@kbn/alerting-plugin/server/types'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; @@ -60,14 +60,13 @@ const MAX_ASSETS_TO_DELETE = 1000; export async function removeInstallation(options: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; pkgName: string; pkgVersion?: string; esClient: ElasticsearchClient; force?: boolean; installSource?: InstallSource; }): Promise { - const { savedObjectsClient, alertingRulesClient, pkgName, pkgVersion, esClient } = options; + const { savedObjectsClient, pkgName, pkgVersion, esClient } = options; const installation = await getInstallation({ savedObjectsClient, pkgName }); if (!installation) { throw new PackageRemovalError(`${pkgName} is not installed`); @@ -104,7 +103,7 @@ export async function removeInstallation(options: { // Delete the installed assets. Don't include installation.package_assets. Those are irrelevant to users const installedAssets = [...installation.installed_kibana, ...installation.installed_es]; - await deleteAssets(savedObjectsClient, alertingRulesClient, installation, esClient); + await deleteAssets(savedObjectsClient, installation, esClient); // Delete the manager saved object with references to the asset objects // could also update with [] or some other state @@ -145,13 +144,11 @@ export async function removeInstallation(options: { */ export async function deleteKibanaAssets({ installedObjects, - alertingRulesClient, packageSpecConditions, logger, spaceId = DEFAULT_SPACE_ID, }: { installedObjects: KibanaAssetReference[]; - alertingRulesClient: RulesClientApi; logger: Logger; packageSpecConditions?: PackageSpecConditions; spaceId?: string; @@ -173,16 +170,8 @@ export async function deleteKibanaAssets({ // only in 8.x or later. If so, we can skip SO resolution step altogether // and delete the assets directly. Otherwise, we need to resolve the assets // which might create high memory pressure if a package has a lot of assets. - const [alertAssets, soAssets] = partition( - installedObjects, - (installedObject) => installedObject.type === 'alert' - ); - if (minKibana && minKibana.major >= 8) { - await Promise.all([ - bulkDeleteSavedObjects(soAssets, namespace, savedObjectsClient, logger), - bulkDeleteAlertRules(alertAssets, alertingRulesClient, logger), - ]); + await bulkDeleteSavedObjects(installedObjects, namespace, savedObjectsClient, logger); } else { const { resolved_objects: resolvedObjects } = await savedObjectsClient.bulkResolve( installedObjects, @@ -234,30 +223,6 @@ async function bulkDeleteSavedObjects( } } -async function bulkDeleteAlertRules( - alertRulesToDelete: Array<{ id: string; type: string }>, - alertingRulesClient: RulesClientApi, - logger: Logger -) { - logger.debug(`Starting bulk deletion of alert rules`); - for (const alertRule of alertRulesToDelete) { - logger.debug(`Delete asset - id: ${alertRule?.id}, type: ${alertRule?.type},`); - auditLoggingService.writeCustomSoAuditLog({ - action: 'delete', - id: alertRule.id, - savedObjectType: alertRule.type, - }); - } - // Delete alert rules in chunks to avoid high memory pressure. This is mostly - // relevant for packages containing many assets, as large payload and response - // objects are created in memory during the delete operation. While chunking - // may work slower, it allows garbage collection to clean up memory between - // requests. - for (const alertRulesChunk of chunk(alertRulesToDelete, MAX_ASSETS_TO_DELETE)) { - await alertingRulesClient.bulkDeleteRules({ ids: alertRulesChunk.map(({ id }) => id) }); - } -} - export const deleteESAsset = async ( installedObject: EsAssetReference, esClient: ElasticsearchClient @@ -375,7 +340,6 @@ export async function deletePrerequisiteAssets( async function deleteAssets( savedObjectsClient: SavedObjectsClientContract, - alertingRulesClient: RulesClientApi, { installed_es: installedEs, installed_kibana: installedKibana, @@ -414,7 +378,6 @@ async function deleteAssets( ...deleteESAssets(otherAssets, esClient), deleteKibanaAssets({ installedObjects: installedKibana, - alertingRulesClient, spaceId, packageSpecConditions: packageInfo?.conditions, logger, @@ -422,7 +385,6 @@ async function deleteAssets( Object.entries(installedInAdditionalSpacesKibana).map(([additionalSpaceId, kibanaAssets]) => deleteKibanaAssets({ installedObjects: kibanaAssets, - alertingRulesClient, spaceId: additionalSpaceId, logger, packageSpecConditions: packageInfo?.conditions, @@ -461,12 +423,10 @@ async function deleteComponentTemplate(esClient: ElasticsearchClient, name: stri export async function deleteKibanaSavedObjectsAssets({ savedObjectsClient, - alertingRulesClient, installedPkg, spaceId, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClientApi; installedPkg: SavedObject; spaceId?: string; }) { @@ -498,7 +458,6 @@ export async function deleteKibanaSavedObjectsAssets({ await deleteKibanaAssets({ installedObjects: assetsToDelete, - alertingRulesClient, spaceId: spaceIdToDelete, packageSpecConditions: packageInfo?.conditions, logger, @@ -566,10 +525,9 @@ export async function cleanupAssets( installationToDelete: Installation, originalInstallation: Installation, esClient: ElasticsearchClient, - alertingRulesClient: RulesClientApi, soClient: SavedObjectsClientContract ) { - await deleteAssets(soClient, alertingRulesClient, installationToDelete, esClient); + await deleteAssets(soClient, installationToDelete, esClient); const { installed_es: installedEs, From 53614cceb941bc0fc455100d5fefa0be507f6cb7 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:28 -0700 Subject: [PATCH 21/41] Revert "Support asset tags for alert rules" This reverts commit 07808318760f325da71fe24a125dabdc90c979a9. --- .../services/epm/kibana/assets/alert_rules.ts | 22 ++----------------- 1 file changed, 2 insertions(+), 20 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index 2a940baca8618..e4186a39e9e39 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -106,7 +106,7 @@ async function installAlertRule({ logger, alertingRulesClient, alertRuleAsset, - context, + context: { pkgName, spaceId, assetTags }, }: { logger: Logger; alertingRulesClient: RulesClient; @@ -114,7 +114,7 @@ async function installAlertRule({ context: InstallAlertRulesParamsContext; }) { const { template: alertRule, id } = alertRuleAsset; - const tags = getTags(id, context); + const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; const createData = transformToCreateAlertRule(alertRule, tags); @@ -161,24 +161,6 @@ function transformToCreateAlertRule(template: AlertRuleAsset['template'], tags: }; } -function getTags(id: string, context: InstallAlertRulesParamsContext) { - const { pkgName, spaceId, assetTags } = context; - const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; - - if (!assetTags || assetTags.length === 0) { - return tags; - } - - const filteredAssetTags = assetTags.reduce((_assetTags, assetTag) => { - if (assetTag.asset_types?.includes('alert') || assetTag.asset_ids?.includes(id)) { - return [..._assetTags, assetTag.text]; - } - return _assetTags; - }, []); - - return [...tags, ...filteredAssetTags]; -} - function getSuccessesAndErrors(results: Array>) { return results.reduce<{ successes: ObjectReference[]; errors: string[] }>( (acc, result) => { From 93abd82c6d18bace59ff5df1fdb61ad0f534ebcc Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:34 -0700 Subject: [PATCH 22/41] Revert "Include alert rules in pkg install results, support baseline tags" This reverts commit 0372350e1770e28f317ebbb63cd6b60a5d73b9ea. --- .../services/epm/kibana/assets/alert_rules.ts | 103 ++++-------------- .../services/epm/kibana/assets/install.ts | 34 ++---- .../services/epm/kibana/assets/tag_assets.ts | 19 ++-- 3 files changed, 43 insertions(+), 113 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts index e4186a39e9e39..b0c510f1ee789 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts @@ -10,9 +10,7 @@ import type { TypeOf } from '@kbn/config-schema'; import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; -import { KibanaSavedObjectType, type PackageSpecTags } from '../../../../types'; - -import { getManagedTagId, getPackageTagId } from './tag_assets'; +import type { KibanaSavedObjectType } from '../../../../types'; export interface AlertRuleAsset { id: string; @@ -20,83 +18,46 @@ export interface AlertRuleAsset { template: Omit, 'actions'>; } -interface ObjectReference { - type: string; - id: string; -} - -interface InstallAlertRulesParamsContext { - pkgName: string; - spaceId: string; - assetTags?: PackageSpecTags[]; -} - -interface InstallAlertRulesParams { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAssets: AlertRuleAsset[]; - context: InstallAlertRulesParamsContext; - assetsChunkSize?: number; -} - export async function installAlertRules({ logger, alertingRulesClient, alertRuleAssets, - context, assetsChunkSize, -}: InstallAlertRulesParams): Promise { - let results: Array> = []; - +}: { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAssets: AlertRuleAsset[]; + assetsChunkSize?: number; +}) { if (!assetsChunkSize || alertRuleAssets.length <= assetsChunkSize) { - results = await installAlertRuleChunk({ + return await installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets }); + } + + const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); + const results = []; + for (const alertRuleChunk of alertRuleChunks) { + const result = await installAlertRuleChunk({ logger, alertingRulesClient, - alertRuleAssets, - context, + alertRuleAssets: alertRuleChunk, }); - } else { - const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); - - for (const alertRuleChunk of alertRuleChunks) { - const result = await installAlertRuleChunk({ - logger, - alertingRulesClient, - alertRuleAssets: alertRuleChunk, - context, - }); - results = [...results, ...result]; - } + results.push(result); } - const { successes, errors } = getSuccessesAndErrors(results); - - if (errors.length > 0) { - throw new Error( - `Encountered ${errors.length} errors installing alert rule assets: ${JSON.stringify( - errors, - null, - 2 - )}` - ); - } - - return successes; + return results; } async function installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets, - context, }: { logger: Logger; alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; - context: InstallAlertRulesParamsContext; }) { const alertRuleInstalls = alertRuleAssets.map((alertRuleAsset) => { - return installAlertRule({ logger, alertingRulesClient, alertRuleAsset, context }); + return installAlertRule({ logger, alertingRulesClient, alertRuleAsset }); }); return await Promise.allSettled(alertRuleInstalls); @@ -106,21 +67,18 @@ async function installAlertRule({ logger, alertingRulesClient, alertRuleAsset, - context: { pkgName, spaceId, assetTags }, }: { logger: Logger; alertingRulesClient: RulesClient; alertRuleAsset: AlertRuleAsset; - context: InstallAlertRulesParamsContext; }) { const { template: alertRule, id } = alertRuleAsset; - const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; - const createData = transformToCreateAlertRule(alertRule, tags); + const createData = transformToCreateAlertRule(alertRule); try { const result = await alertingRulesClient.create({ data: createData, options: { id } }); - return { id: result.id, type: KibanaSavedObjectType.alert }; + return result; } catch (e) { // Already exists if (e?.output?.statusCode === 409) { @@ -128,13 +86,13 @@ async function installAlertRule({ data: createData, id, }); - return { id: result.id, type: KibanaSavedObjectType.alert }; + return result; } throw e; } } -function transformToCreateAlertRule(template: AlertRuleAsset['template'], tags: string[]) { +function transformToCreateAlertRule(template: AlertRuleAsset['template']) { const { rule_type_id: _ruleTypeId, alert_delay: _alertDelay, @@ -155,22 +113,9 @@ function transformToCreateAlertRule(template: AlertRuleAsset['template'], tags: : undefined, ...(template.alert_delay ? { alertDelay: template.alert_delay } : {}), ...(template.notify_when ? { notifyWhen: template.notify_when } : {}), + // Always include 'Managed' tag + tags: [...new Set([...template.tags, 'Managed'])], // Always no prescribed actions actions: [], - tags: [...new Set([...baseCreateData.tags, ...tags])], }; } - -function getSuccessesAndErrors(results: Array>) { - return results.reduce<{ successes: ObjectReference[]; errors: string[] }>( - (acc, result) => { - if (result.status === 'fulfilled') { - acc.successes = [...acc.successes, result.value]; - } else { - acc.errors = [...acc.errors, result.reason]; - } - return acc; - }, - { successes: [], errors: [] } - ); -} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 6d2fe50eacc77..d8971bd37689e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -24,7 +24,6 @@ import { getPathParts } from '../../archive'; import { KibanaAssetType, KibanaSavedObjectType } from '../../../../types'; import type { AssetReference, Installation, PackageSpecTags } from '../../../../types'; import type { KibanaAssetReference, PackageInstallContext } from '../../../../../common/types'; -import { MAX_CONCURRENT_PACKAGE_ASSETS } from '../../../../constants'; import { indexPatternTypes, getIndexPatternSavedObjects, @@ -43,11 +42,6 @@ import { installAlertRules, type AlertRuleAsset } from './alert_rules'; const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 200; -interface ObjectReference { - type: string; - id: string; -} - type SavedObjectsImporterContract = Pick; const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => JSON.stringify( @@ -141,23 +135,18 @@ export async function installKibanaAssets(options: { alertingRulesClient: RulesClient; logger: Logger; pkgName: string; - spaceId: string; - assetTags?: PackageSpecTags[]; kibanaAssetsArchiveIterator: ReturnType; -}): Promise> { +}): Promise { const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, alertingRulesClient, logger, - pkgName, - spaceId, - assetTags, } = options; let assetsToInstall: ArchiveAssetEntry[] = []; - let res: Array = []; + let res: SavedObjectsImportSuccess[] = []; const installManagedIndexPatternOnce = once(() => installManagedIndexPattern({ @@ -171,7 +160,7 @@ export async function installKibanaAssets(options: { asAlertRules: AlertRuleAsset[]; } const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { - return assetEntries.reduce( + return assetsToInstall.reduce( (installGroups, assetEntry) => { if (assetEntry.assetType === KibanaAssetType.alert) { installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; @@ -191,12 +180,11 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - const installedAlertRules = await installAlertRules({ + await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules, - assetsChunkSize: MAX_CONCURRENT_PACKAGE_ASSETS, - context: { pkgName, spaceId, assetTags }, + assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); const installedAssets = await installKibanaSavedObjects({ @@ -206,7 +194,7 @@ export async function installKibanaAssets(options: { assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); assetsToInstall = []; - res = [...res, ...installedAssets, ...installedAlertRules]; + res = [...res, ...installedAssets]; } await kibanaAssetsArchiveIterator(async (entry) => { @@ -367,16 +355,14 @@ export async function installKibanaAssetsAndReferences({ savedObjectsImporter, alertingRulesClient, pkgName, - spaceId, - assetTags, kibanaAssetsArchiveIterator, }); const assets = importedAssets.map( - (asset) => + ({ id, type, destinationId }) => ({ - id: 'destinationId' in asset && asset.destinationId ? asset.destinationId : asset.id, - ...('destinationId' in asset && asset.destinationId ? { originId: asset.id } : {}), - type: asset.type, + id: destinationId ?? id, + ...(destinationId ? { originId: id } : {}), + type, } as KibanaAssetReference) ); installedKibanaAssetsRefs = await saveKibanaAssetsRefs( diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts index 34328284e3ce4..bebc0ba9dc810 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts @@ -55,9 +55,8 @@ const TAG_COLORS = [ '#A0A0A0', ]; -export const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; -export const getPackageTagId = (spaceId: string, pkgName: string) => - `fleet-pkg-${pkgName}-${spaceId}`; +const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; +const getPackageTagId = (spaceId: string, pkgName: string) => `fleet-pkg-${pkgName}-${spaceId}`; const getLegacyPackageTagId = (pkgName: string) => pkgName; /* @@ -86,12 +85,12 @@ interface TagAssetsParams { pkgTitle: string; pkgName: string; spaceId: string; - importedAssets: Array; + importedAssets: SavedObjectsImportSuccess[]; assetTags?: PackageSpecTags[]; } -const getNewId = (asset: ObjectReference | SavedObjectsImportSuccess) => - 'destinationId' in asset && asset?.destinationId ? asset.destinationId : asset.id; +const getNewId = (asset: SavedObjectsImportSuccess) => + asset?.destinationId ? asset.destinationId : asset.id; export async function tagKibanaAssets(opts: TagAssetsParams) { const { savedObjectTagAssignmentService, importedAssets } = opts; @@ -148,7 +147,7 @@ export async function tagKibanaAssets(opts: TagAssetsParams) { } } -function getTaggableAssets(importedAssets: Array) { +function getTaggableAssets(importedAssets: SavedObjectsImportSuccess[]) { return importedAssets.filter((asset) => taggableTypes.includes(asset.type)); } @@ -207,7 +206,7 @@ async function ensurePackageTag( // Ensure that asset tags coming from the kibana/tags.yml file are correctly parsed and created async function getPackageSpecTags( - taggableAssets: Array, + taggableAssets: SavedObjectsImportSuccess[], opts: Pick ): Promise { const { spaceId, savedObjectTagClient, pkgName, assetTags } = opts; @@ -242,7 +241,7 @@ async function getPackageSpecTags( // Get all the assets of types defined in tag.asset_types from taggable kibanaAssets const getAssetTypesObjectReferences = ( assetTypes: string[] | undefined, - taggableAssets: Array + taggableAssets: SavedObjectsImportSuccess[] ): ObjectReference[] => { if (!assetTypes || assetTypes.length === 0) return []; @@ -256,7 +255,7 @@ const getAssetTypesObjectReferences = ( // Get the references to ids defined in tag.asset_ids from taggable kibanaAssets const getAssetIdsObjectReferences = ( assetIds: string[] | undefined, - taggableAssets: Array + taggableAssets: SavedObjectsImportSuccess[] ): ObjectReference[] => { if (!assetIds || assetIds.length === 0) return []; From 9cd9f14331501cd911d2040985581c144a01bfb5 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:39 -0700 Subject: [PATCH 23/41] Revert "Handle installing multiple alert assets" This reverts commit e46caf169ead241c29b25a21957e477fcb301ac8. --- .../services/epm/kibana/assets/alert_rules.ts | 121 ------------------ .../services/epm/kibana/assets/install.ts | 60 ++++++++- 2 files changed, 53 insertions(+), 128 deletions(-) delete mode 100644 x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts deleted file mode 100644 index b0c510f1ee789..0000000000000 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert_rules.ts +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ -import { chunk } from 'lodash'; -import type { Logger } from '@kbn/core/server'; -import type { TypeOf } from '@kbn/config-schema'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; -import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; - -import type { KibanaSavedObjectType } from '../../../../types'; - -export interface AlertRuleAsset { - id: string; - type: KibanaSavedObjectType.alert; - template: Omit, 'actions'>; -} - -export async function installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets, - assetsChunkSize, -}: { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAssets: AlertRuleAsset[]; - assetsChunkSize?: number; -}) { - if (!assetsChunkSize || alertRuleAssets.length <= assetsChunkSize) { - return await installAlertRuleChunk({ logger, alertingRulesClient, alertRuleAssets }); - } - - const alertRuleChunks = chunk(alertRuleAssets, assetsChunkSize); - const results = []; - for (const alertRuleChunk of alertRuleChunks) { - const result = await installAlertRuleChunk({ - logger, - alertingRulesClient, - alertRuleAssets: alertRuleChunk, - }); - results.push(result); - } - - return results; -} - -async function installAlertRuleChunk({ - logger, - alertingRulesClient, - alertRuleAssets, -}: { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAssets: AlertRuleAsset[]; -}) { - const alertRuleInstalls = alertRuleAssets.map((alertRuleAsset) => { - return installAlertRule({ logger, alertingRulesClient, alertRuleAsset }); - }); - - return await Promise.allSettled(alertRuleInstalls); -} - -async function installAlertRule({ - logger, - alertingRulesClient, - alertRuleAsset, -}: { - logger: Logger; - alertingRulesClient: RulesClient; - alertRuleAsset: AlertRuleAsset; -}) { - const { template: alertRule, id } = alertRuleAsset; - - const createData = transformToCreateAlertRule(alertRule); - - try { - const result = await alertingRulesClient.create({ data: createData, options: { id } }); - return result; - } catch (e) { - // Already exists - if (e?.output?.statusCode === 409) { - const result = await alertingRulesClient.update({ - data: createData, - id, - }); - return result; - } - throw e; - } -} - -function transformToCreateAlertRule(template: AlertRuleAsset['template']) { - const { - rule_type_id: _ruleTypeId, - alert_delay: _alertDelay, - notify_when: _notifyWhen, - ...baseCreateData - } = template; - - return { - ...baseCreateData, - // Always disabled - enabled: false, - alertTypeId: template.rule_type_id, - flapping: template.flapping - ? { - lookBackWindow: template.flapping.look_back_window, - statusChangeThreshold: template.flapping.status_change_threshold, - } - : undefined, - ...(template.alert_delay ? { alertDelay: template.alert_delay } : {}), - ...(template.notify_when ? { notifyWhen: template.notify_when } : {}), - // Always include 'Managed' tag - tags: [...new Set([...template.tags, 'Managed'])], - // Always no prescribed actions - actions: [], - }; -} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index d8971bd37689e..f1bfcc456533e 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,6 +16,8 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; +import type { TypeOf } from '@kbn/config-schema'; +import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -38,7 +40,6 @@ import { appContextService } from '../../..'; import { tagKibanaAssets } from './tag_assets'; import { getSpaceAwareSaveobjectsClients } from './saved_objects'; -import { installAlertRules, type AlertRuleAsset } from './alert_rules'; const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 200; @@ -56,6 +57,11 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; +interface AlertRuleAsset { + id: string; + type: KibanaSavedObjectType.alert; + template: Omit, 'actions'>; +} type SavedObjectAsset = Pick< SavedObject, | 'id' @@ -180,12 +186,7 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - await installAlertRules({ - logger, - alertingRulesClient, - alertRuleAssets: asAlertRules, - assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, - }); + await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules }); const installedAssets = await installKibanaSavedObjects({ logger, @@ -650,3 +651,48 @@ export function toAssetReference({ id, type }: SavedObject) { function hasReferences(assetsToInstall: SavedObjectAsset[]) { return assetsToInstall.some((asset) => asset.references.length); } + +async function installAlertRules({ + logger, + alertingRulesClient, + alertRuleAssets, +}: { + logger: Logger; + alertingRulesClient: RulesClient; + alertRuleAssets: AlertRuleAsset[]; +}): Promise { + logger.debug(`create alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); + const { template: alertRule, id } = alertRuleAssets[0]; + + const { + rule_type_id: _ruleTypeId, + alert_delay: _alertDelay, + notify_when: _notifyWhen, + ...baseCreateData + } = alertRule; + + const createData = { + ...baseCreateData, + alertTypeId: alertRule.rule_type_id, + flapping: alertRule.flapping + ? { + lookBackWindow: alertRule.flapping.look_back_window, + statusChangeThreshold: alertRule.flapping.status_change_threshold, + } + : undefined, + ...(alertRule.alert_delay ? { alertDelay: alertRule.alert_delay } : {}), + ...(alertRule.notify_when ? { notifyWhen: alertRule.notify_when } : {}), + actions: [], + }; + + try { + await alertingRulesClient.create({ data: createData, options: { id } }); + } catch (e) { + if (e?.output?.statusCode === 409) { + await alertingRulesClient.update({ + data: createData, + id, + }); + } + } +} From d6cb7fb38c5a227be5711cbdfd2660ffc7e05cf7 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:44 -0700 Subject: [PATCH 24/41] Revert "Establish steel thread for creating alert assets" This reverts commit 76e018c9f70ef1af51a21936bd092b2ab59432cd. --- .../plugins/shared/fleet/kibana.jsonc | 14 ++-- .../services/epm/kibana/assets/install.ts | 65 ++----------------- .../kibana/assets/install_with_streaming.ts | 2 - .../server/services/epm/packages/install.ts | 1 - .../steps/step_install_kibana_assets.ts | 13 +--- 5 files changed, 19 insertions(+), 76 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/kibana.jsonc b/x-pack/platform/plugins/shared/fleet/kibana.jsonc index f88bd25a3a133..e4139e517f107 100644 --- a/x-pack/platform/plugins/shared/fleet/kibana.jsonc +++ b/x-pack/platform/plugins/shared/fleet/kibana.jsonc @@ -1,16 +1,20 @@ { "type": "plugin", "id": "@kbn/fleet-plugin", - "owner": ["@elastic/fleet"], + "owner": [ + "@elastic/fleet" + ], "group": "platform", "visibility": "shared", "plugin": { "id": "fleet", "browser": true, "server": true, - "configPath": ["xpack", "fleet"], + "configPath": [ + "xpack", + "fleet" + ], "requiredPlugins": [ - "alerting", "licensing", "data", "encryptedSavedObjects", @@ -49,6 +53,8 @@ "usageCollection", "unifiedSearch" ], - "extraPublicDirs": ["common"] + "extraPublicDirs": [ + "common" + ] } } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index f1bfcc456533e..f90c8579d39af 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,9 +16,8 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -import type { TypeOf } from '@kbn/config-schema'; +// import { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -57,11 +56,10 @@ type SavedObjectToBe = Required< type: KibanaSavedObjectType; }; -interface AlertRuleAsset { +type AlertRuleAsset = typeof alertRuleBodySchema & { id: string; type: KibanaSavedObjectType.alert; - template: Omit, 'actions'>; -} +}; type SavedObjectAsset = Pick< SavedObject, | 'id' @@ -138,18 +136,11 @@ export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObje export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; - alertingRulesClient: RulesClient; logger: Logger; pkgName: string; kibanaAssetsArchiveIterator: ReturnType; }): Promise { - const { - kibanaAssetsArchiveIterator, - savedObjectsClient, - savedObjectsImporter, - alertingRulesClient, - logger, - } = options; + const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger } = options; let assetsToInstall: ArchiveAssetEntry[] = []; let res: SavedObjectsImportSuccess[] = []; @@ -186,7 +177,7 @@ export async function installKibanaAssets(options: { // split assets into SO installs and alert rule installs const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - await installAlertRules({ logger, alertingRulesClient, alertRuleAssets: asAlertRules }); + await installAlertRules({ logger, alertRuleAssets: asAlertRules }); const installedAssets = await installKibanaSavedObjects({ logger, @@ -248,7 +239,6 @@ export async function createDefaultIndexPatterns( export async function installKibanaAssetsAndReferencesMultispace({ savedObjectsClient, - alertingRulesClient, logger, pkgName, pkgTitle, @@ -259,7 +249,6 @@ export async function installKibanaAssetsAndReferencesMultispace({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -273,7 +262,6 @@ export async function installKibanaAssetsAndReferencesMultispace({ // Install in every space => upgrades const refs = await installKibanaAssetsAndReferences({ savedObjectsClient, - alertingRulesClient, logger, pkgName, pkgTitle, @@ -289,7 +277,6 @@ export async function installKibanaAssetsAndReferencesMultispace({ )) { await installKibanaAssetsAndReferences({ savedObjectsClient, - alertingRulesClient, logger, pkgName, pkgTitle, @@ -305,7 +292,6 @@ export async function installKibanaAssetsAndReferencesMultispace({ return installKibanaAssetsAndReferences({ savedObjectsClient, - alertingRulesClient, logger, pkgName, pkgTitle, @@ -319,7 +305,6 @@ export async function installKibanaAssetsAndReferencesMultispace({ export async function installKibanaAssetsAndReferences({ savedObjectsClient, - alertingRulesClient, logger, pkgName, pkgTitle, @@ -330,7 +315,6 @@ export async function installKibanaAssetsAndReferences({ installAsAdditionalSpace, }: { savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; logger: Logger; pkgName: string; pkgTitle: string; @@ -354,7 +338,6 @@ export async function installKibanaAssetsAndReferences({ savedObjectsClient, logger, savedObjectsImporter, - alertingRulesClient, pkgName, kibanaAssetsArchiveIterator, }); @@ -654,45 +637,11 @@ function hasReferences(assetsToInstall: SavedObjectAsset[]) { async function installAlertRules({ logger, - alertingRulesClient, alertRuleAssets, }: { logger: Logger; - alertingRulesClient: RulesClient; alertRuleAssets: AlertRuleAsset[]; }): Promise { - logger.debug(`create alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); - const { template: alertRule, id } = alertRuleAssets[0]; - - const { - rule_type_id: _ruleTypeId, - alert_delay: _alertDelay, - notify_when: _notifyWhen, - ...baseCreateData - } = alertRule; - - const createData = { - ...baseCreateData, - alertTypeId: alertRule.rule_type_id, - flapping: alertRule.flapping - ? { - lookBackWindow: alertRule.flapping.look_back_window, - statusChangeThreshold: alertRule.flapping.status_change_threshold, - } - : undefined, - ...(alertRule.alert_delay ? { alertDelay: alertRule.alert_delay } : {}), - ...(alertRule.notify_when ? { notifyWhen: alertRule.notify_when } : {}), - actions: [], - }; - - try { - await alertingRulesClient.create({ data: createData, options: { id } }); - } catch (e) { - if (e?.output?.statusCode === 409) { - await alertingRulesClient.update({ - data: createData, - id, - }); - } - } + logger.debug(`no-op alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); + return Promise.resolve(); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index 2941fbb78bc8a..b424d71b00f62 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -6,7 +6,6 @@ */ import type { SavedObjectsClientContract } from '@kbn/core/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; import type { PackageInstallContext } from '../../../../../common/types'; import type { KibanaAssetReference, KibanaAssetType } from '../../../../types'; @@ -29,7 +28,6 @@ interface InstallKibanaAssetsWithStreamingArgs { packageInstallContext: PackageInstallContext; spaceId: string; savedObjectsClient: SavedObjectsClientContract; - alertingRulesClient: RulesClient; } const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 100; diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index da0d45801b9ee..f317d98a3e4e9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -751,7 +751,6 @@ export async function installPackageWithStateMachine(options: { savedObjectTagAssignmentService, savedObjectTagClient, esClient, - alertingRulesClient, logger, installedPkg, packageInstallContext, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts index 0eb7c137fbd33..ba8f71123eb6d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts @@ -16,21 +16,13 @@ import { INSTALL_STATES } from '../../../../../../common/types'; import { installKibanaAssetsWithStreaming } from '../../../kibana/assets/install_with_streaming'; export async function stepInstallKibanaAssets(context: InstallContext) { - const { - savedObjectsClient, - alertingRulesClient, - logger, - installedPkg, - packageInstallContext, - spaceId, - } = context; + const { savedObjectsClient, logger, installedPkg, packageInstallContext, spaceId } = context; const { packageInfo } = packageInstallContext; const { name: pkgName, title: pkgTitle } = packageInfo; const kibanaAssetPromise = withPackageSpan('Install Kibana assets', () => installKibanaAssetsAndReferencesMultispace({ savedObjectsClient, - alertingRulesClient, pkgName, pkgTitle, packageInstallContext, @@ -48,7 +40,7 @@ export async function stepInstallKibanaAssets(context: InstallContext) { } export async function stepInstallKibanaAssetsWithStreaming(context: InstallContext) { - const { savedObjectsClient, alertingRulesClient, packageInstallContext, spaceId } = context; + const { savedObjectsClient, packageInstallContext, spaceId } = context; const { packageInfo } = packageInstallContext; const { name: pkgName } = packageInfo; @@ -57,7 +49,6 @@ export async function stepInstallKibanaAssetsWithStreaming(context: InstallConte () => installKibanaAssetsWithStreaming({ savedObjectsClient, - alertingRulesClient, pkgName, packageInstallContext, spaceId, From 5bb3b9ec81d03e1241e4e046ace93934e05d042d Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 08:46:47 -0700 Subject: [PATCH 25/41] Revert "WIP: Add alertingStart to app context, and alertingRulesClient to package install" This reverts commit 3a0802d12a10c7225a8fb98f0499eb25f62aa753. --- .../plugins/shared/fleet/server/plugin.ts | 5 +--- .../fleet/server/routes/epm/handlers.ts | 13 +------- .../fleet/server/services/app_context.ts | 7 ----- .../server/services/epm/packages/install.ts | 30 ++----------------- 4 files changed, 4 insertions(+), 51 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/plugin.ts b/x-pack/platform/plugins/shared/fleet/server/plugin.ts index 4825753815761..83627f6e7a3db 100644 --- a/x-pack/platform/plugins/shared/fleet/server/plugin.ts +++ b/x-pack/platform/plugins/shared/fleet/server/plugin.ts @@ -40,7 +40,6 @@ import type { SecurityPluginSetup, SecurityPluginStart, } from '@kbn/security-plugin/server'; -import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { FeaturesPluginSetup } from '@kbn/features-plugin/server'; import type { FieldsMetadataServerSetup } from '@kbn/fields-metadata-plugin/server'; import type { @@ -167,7 +166,6 @@ export interface FleetStartDeps { data: DataPluginStart; licensing: LicensingPluginStart; encryptedSavedObjects: EncryptedSavedObjectsPluginStart; - alerting: AlertingServerStart; security: SecurityPluginStart; telemetry?: TelemetryPluginStart; savedObjectsTagging: SavedObjectTaggingStart; @@ -180,7 +178,6 @@ export interface FleetAppContext { data: DataPluginStart; encryptedSavedObjectsStart?: EncryptedSavedObjectsPluginStart; encryptedSavedObjectsSetup?: EncryptedSavedObjectsPluginSetup; - alertingStart: AlertingServerStart; securityCoreStart: SecurityServiceStart; securitySetup: SecurityPluginSetup; securityStart: SecurityPluginStart; @@ -558,6 +555,7 @@ export class FleetPlugin const routeAuthz = routeRequiredAuthz ? calculateRouteAuthz(authz, routeRequiredAuthz) : undefined; + const getInternalSoClient = (): SavedObjectsClientContract => appContextService .getSavedObjects() @@ -714,7 +712,6 @@ export class FleetPlugin data: plugins.data, encryptedSavedObjectsStart: plugins.encryptedSavedObjects, encryptedSavedObjectsSetup: this.encryptedSavedObjectsSetup, - alertingStart: plugins.alerting, securityCoreStart: core.security, securitySetup: this.securitySetup, securityStart: plugins.security, diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts index 979e694fa5657..50448f9431a8f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/handlers.ts @@ -303,10 +303,8 @@ export const installPackageFromRegistryHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; + const { pkgName, pkgVersion } = request.params; const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username); @@ -318,7 +316,6 @@ export const installPackageFromRegistryHandler: FleetRequestHandler< savedObjectsClient, pkgkey: pkgVersion ? `${pkgName}-${pkgVersion}` : pkgName, esClient, - alertingRulesClient, spaceId, force: request.body?.force, ignoreConstraints: request.body?.ignore_constraints, @@ -351,9 +348,6 @@ export const createCustomIntegrationHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const user = appContextService.getSecurityCore().authc.getCurrentUser(request) || undefined; const kibanaVersion = appContextService.getKibanaVersion(); const authorizationHeader = HTTPAuthorizationHeader.parseFromRequest(request, user?.username); @@ -367,7 +361,6 @@ export const createCustomIntegrationHandler: FleetRequestHandler< pkgName: integrationName, datasets, esClient, - alertingRulesClient, spaceId, force, authorizationHeader, @@ -484,9 +477,6 @@ export const installPackageByUploadHandler: FleetRequestHandler< const fleetContext = await context.fleet; const savedObjectsClient = fleetContext.internalSoClient; const esClient = coreContext.elasticsearch.client.asInternalUser; - const alertingRulesClient = await appContextService - .getAlerting() - .getRulesClientWithRequest(request); const contentType = request.headers['content-type'] as string; // from types it could also be string[] or undefined but this is checked later const archiveBuffer = Buffer.from(request.body); const spaceId = fleetContext.spaceId; @@ -497,7 +487,6 @@ export const installPackageByUploadHandler: FleetRequestHandler< installSource, savedObjectsClient, esClient, - alertingRulesClient, archiveBuffer, spaceId, contentType, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts index 83990d3d94fdd..52c35739d2208 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts @@ -11,7 +11,6 @@ import { kibanaPackageJson } from '@kbn/repo-info'; import type { HttpServiceSetup, KibanaRequest } from '@kbn/core-http-server'; import { kibanaRequestFactory } from '@kbn/core-http-server-utils'; -import type { AlertingServerStart } from '@kbn/alerting-plugin/server'; import type { PluginStart as DataPluginStart } from '@kbn/data-plugin/server'; import type { EncryptedSavedObjectsClient, @@ -63,7 +62,6 @@ class AppContextService { private data: DataPluginStart | undefined; private esClient: ElasticsearchClient | undefined; private experimentalFeatures: ExperimentalFeatures = allowedExperimentalValues; - private alertingStart: AlertingServerStart | undefined; private securityCoreStart: SecurityServiceStart | undefined; private securitySetup: SecurityPluginSetup | undefined; private securityStart: SecurityPluginStart | undefined; @@ -93,7 +91,6 @@ class AppContextService { this.encryptedSavedObjectsStart = appContext.encryptedSavedObjectsStart; this.encryptedSavedObjects = appContext.encryptedSavedObjectsStart?.getClient(); this.encryptedSavedObjectsSetup = appContext.encryptedSavedObjectsSetup; - this.alertingStart = appContext.alertingStart; this.securityCoreStart = appContext.securityCoreStart; this.securitySetup = appContext.securitySetup; this.securityStart = appContext.securityStart; @@ -141,10 +138,6 @@ class AppContextService { return this.encryptedSavedObjects; } - public getAlerting() { - return this.alertingStart!; - } - public getSecurityCore() { return this.securityCoreStart!; } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index f317d98a3e4e9..da15fe5a86806 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -21,7 +21,6 @@ import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import { DEFAULT_SPACE_ID } from '@kbn/spaces-plugin/common/constants'; import pRetry from 'p-retry'; import type { LicenseType } from '@kbn/licensing-plugin/server'; -import type { RulesClient } from '@kbn/alerting-plugin/server'; import type { KibanaAssetReference, @@ -175,7 +174,6 @@ export async function ensureInstalledPackage(options: { savedObjectsClient: SavedObjectsClientContract; pkgName: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; pkgVersion?: string; spaceId?: string; force?: boolean; @@ -185,7 +183,6 @@ export async function ensureInstalledPackage(options: { savedObjectsClient, pkgName, esClient, - alertingRulesClient, pkgVersion, force = false, spaceId = DEFAULT_SPACE_ID, @@ -218,7 +215,6 @@ export async function ensureInstalledPackage(options: { pkgkey, spaceId, esClient, - alertingRulesClient, neverIgnoreVerificationError: !force, force: true, // Always force outdated packages to be installed if a later version isn't installed authorizationHeader, @@ -274,7 +270,6 @@ export async function handleInstallPackageFailure({ pkgVersion, installedPkg, esClient, - alertingRulesClient, spaceId, authorizationHeader, keepFailedInstallation, @@ -285,7 +280,6 @@ export async function handleInstallPackageFailure({ pkgVersion: string; installedPkg: SavedObject | undefined; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; spaceId: string; authorizationHeader?: HTTPAuthorizationHeader | null; keepFailedInstallation?: boolean; @@ -343,7 +337,6 @@ export async function handleInstallPackageFailure({ savedObjectsClient, pkgkey, esClient, - alertingRulesClient, spaceId, authorizationHeader, retryFromLastState: true, @@ -365,7 +358,6 @@ export async function handleInstallPackageFailure({ savedObjectsClient, pkgkey: prevVersion, esClient, - alertingRulesClient, spaceId, force: true, authorizationHeader, @@ -402,7 +394,6 @@ interface InstallRegistryPackageParams { savedObjectsClient: SavedObjectsClientContract; pkgkey: string; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; spaceId: string; force?: boolean; neverIgnoreVerificationError?: boolean; @@ -426,7 +417,6 @@ interface InstallCustomPackageParams { pkgName: string; datasets: CustomPackageDatasetConfiguration[]; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; spaceId: string; force?: boolean; authorizationHeader?: HTTPAuthorizationHeader | null; @@ -435,7 +425,6 @@ interface InstallCustomPackageParams { interface InstallUploadedArchiveParams { savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; archiveBuffer: Buffer; contentType: string; spaceId: string; @@ -471,7 +460,6 @@ async function installPackageFromRegistry({ savedObjectsClient, pkgkey, esClient, - alertingRulesClient, spaceId, authorizationHeader, force = false, @@ -577,7 +565,6 @@ async function installPackageFromRegistry({ installType, savedObjectsClient, esClient, - alertingRulesClient, spaceId, force, packageInstallContext, @@ -619,7 +606,6 @@ export async function installPackageWithStateMachine(options: { installType: InstallType; savedObjectsClient: SavedObjectsClientContract; esClient: ElasticsearchClient; - alertingRulesClient: RulesClient; spaceId: string; force?: boolean; packageInstallContext: PackageInstallContext; @@ -645,7 +631,6 @@ export async function installPackageWithStateMachine(options: { savedObjectsClient, force, esClient, - alertingRulesClient, spaceId, verificationResult, authorizationHeader, @@ -796,7 +781,6 @@ export async function installPackageWithStateMachine(options: { installedPkg, spaceId, esClient, - alertingRulesClient, authorizationHeader, keepFailedInstallation, }); @@ -825,7 +809,6 @@ export async function installPackageWithStateMachine(options: { async function installPackageByUpload({ savedObjectsClient, esClient, - alertingRulesClient, archiveBuffer, contentType, spaceId, @@ -910,7 +893,6 @@ async function installPackageByUpload({ installType, savedObjectsClient, esClient, - alertingRulesClient, spaceId, force: true, // upload has implicit force paths, @@ -949,7 +931,7 @@ export async function installPackage(args: InstallPackageParams): Promise Date: Thu, 17 Jul 2025 08:46:52 -0700 Subject: [PATCH 26/41] Revert "Introduce alert rule as epm kibana asset type" This reverts commit 1e826cf5a0ff8050fe026674e2fddfd86288b3ee. --- .../services/epm/kibana/assets/install.ts | 106 +++++------------- .../server/services/epm/packages/install.ts | 9 ++ 2 files changed, 35 insertions(+), 80 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index f90c8579d39af..5d7043c90844d 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -16,8 +16,6 @@ import type { SavedObjectsImportFailure, Logger, } from '@kbn/core/server'; -// import { RulesClient } from '@kbn/alerting-plugin/server/rules_client'; -import type { createBodySchemaV1 as alertRuleBodySchema } from '@kbn/alerting-plugin/common/routes/rule/apis/create'; import { createListStream } from '@kbn/utils'; import { partition, chunk, once } from 'lodash'; @@ -48,19 +46,10 @@ const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => errors.map(({ type, id, error }) => ({ type, id, error })) // discard other fields ); const validKibanaAssetTypes = new Set(Object.values(KibanaAssetType)); - -type SavedObjectKibanaAssetTypes = Exclude; -type SavedObjectToBe = Required< - Pick> -> & { +type SavedObjectToBe = Required> & { type: KibanaSavedObjectType; }; - -type AlertRuleAsset = typeof alertRuleBodySchema & { - id: string; - type: KibanaSavedObjectType.alert; -}; -type SavedObjectAsset = Pick< +export type ArchiveAsset = Pick< SavedObject, | 'id' | 'attributes' @@ -72,25 +61,9 @@ type SavedObjectAsset = Pick< type: KibanaSavedObjectType; }; -export type ArchiveAsset = SavedObjectAsset | AlertRuleAsset; -interface SavedObjectAssetEntry { - path: string; - asset: SavedObjectAsset; - assetType: SavedObjectKibanaAssetTypes; -} - -interface AlertRuleAssetEntry { - path: string; - asset: AlertRuleAsset; - assetType: KibanaAssetType.alert; -} - -type ArchiveAssetEntry = SavedObjectAssetEntry | AlertRuleAssetEntry; - // KibanaSavedObjectTypes are used to ensure saved objects being created for a given // KibanaAssetType have the correct type export const KibanaSavedObjectTypeMapping: Record = { - [KibanaAssetType.alert]: KibanaSavedObjectType.alert, [KibanaAssetType.dashboard]: KibanaSavedObjectType.dashboard, [KibanaAssetType.indexPattern]: KibanaSavedObjectType.indexPattern, [KibanaAssetType.map]: KibanaSavedObjectType.map, @@ -102,16 +75,17 @@ export const KibanaSavedObjectTypeMapping: Record ArchiveAssetEntry[]> = { +const AssetFilters: Record ArchiveAsset[]> = { [KibanaAssetType.indexPattern]: removeReservedIndexPatterns, }; -export function createSavedObjectKibanaAsset(asset: SavedObjectAsset): SavedObjectToBe { +export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectToBe { // convert that to an object const so: Partial = { type: asset.type, @@ -142,7 +116,7 @@ export async function installKibanaAssets(options: { }): Promise { const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger } = options; - let assetsToInstall: ArchiveAssetEntry[] = []; + let assetsToInstall: ArchiveAsset[] = []; let res: SavedObjectsImportSuccess[] = []; const installManagedIndexPatternOnce = once(() => @@ -152,49 +126,25 @@ export async function installKibanaAssets(options: { }) ); - interface InstallGroups { - asSavedObjects: SavedObjectAsset[]; - asAlertRules: AlertRuleAsset[]; - } - const createInstallGroups = (assetEntries: ArchiveAssetEntry[]) => { - return assetsToInstall.reduce( - (installGroups, assetEntry) => { - if (assetEntry.assetType === KibanaAssetType.alert) { - installGroups.asAlertRules = [...installGroups.asAlertRules, assetEntry.asset]; - return installGroups; - } - - installGroups.asSavedObjects = [...installGroups.asSavedObjects, assetEntry.asset]; - return installGroups; - }, - { asSavedObjects: [], asAlertRules: [] } - ); - }; - async function flushAssetsToInstall() { await installManagedIndexPatternOnce(); - // split assets into SO installs and alert rule installs - const { asSavedObjects, asAlertRules } = createInstallGroups(assetsToInstall); - - await installAlertRules({ logger, alertRuleAssets: asAlertRules }); - const installedAssets = await installKibanaSavedObjects({ logger, savedObjectsImporter, - kibanaAssets: asSavedObjects, + kibanaAssets: assetsToInstall, assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); assetsToInstall = []; res = [...res, ...installedAssets]; } - await kibanaAssetsArchiveIterator(async (entry) => { - const assetFilter = AssetFilters[entry.assetType]; + await kibanaAssetsArchiveIterator(async ({ assetType, asset }) => { + const assetFilter = AssetFilters[assetType]; if (assetFilter) { - assetsToInstall = [...assetsToInstall, ...assetFilter([entry])]; + assetsToInstall = [...assetsToInstall, ...assetFilter([asset])]; } else { - assetsToInstall.push(entry); + assetsToInstall.push(asset); } if (assetsToInstall.length >= MAX_ASSETS_TO_INSTALL_IN_PARALLEL) { @@ -407,7 +357,13 @@ export const isKibanaAssetType = (path: string) => { }; function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallContext) { - return (onEntry: (entry: ArchiveAssetEntry) => Promise) => { + return ( + onEntry: (entry: { + path: string; + asset: ArchiveAsset; + assetType: KibanaAssetType; + }) => Promise + ) => { return packageInstallContext.archiveIterator.traverseEntries(async (entry) => { if (!entry.buffer) { return; @@ -416,10 +372,11 @@ function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallCon const asset = JSON.parse(entry.buffer.toString('utf8')); const assetType = getPathParts(entry.path).type as KibanaAssetType; + const soType = KibanaSavedObjectTypeMapping[assetType]; if (!validKibanaAssetTypes.has(assetType)) { return; } - const soType = KibanaSavedObjectTypeMapping[assetType]; + if (asset.type === soType) { await onEntry({ path: entry.path, assetType, asset }); } @@ -467,7 +424,7 @@ export async function installKibanaSavedObjects({ assetsChunkSize, logger, }: { - kibanaAssets: SavedObjectAsset[]; + kibanaAssets: ArchiveAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; assetsChunkSize?: number; @@ -523,7 +480,7 @@ async function installKibanaSavedObjectsChunk({ logger, refresh, }: { - kibanaAssets: SavedObjectAsset[]; + kibanaAssets: ArchiveAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; refresh?: boolean | 'wait_for'; @@ -619,10 +576,10 @@ async function installKibanaSavedObjectsChunk({ } // Filter out any reserved index patterns -function removeReservedIndexPatterns(kibanaAssets: ArchiveAssetEntry[]) { +function removeReservedIndexPatterns(kibanaAssets: ArchiveAsset[]) { const reservedPatterns = indexPatternTypes.map((pattern) => `${pattern}-*`); - return kibanaAssets.filter((assetEntry) => !reservedPatterns.includes(assetEntry.asset.id)); + return kibanaAssets.filter((asset) => !reservedPatterns.includes(asset.id)); } export function toAssetReference({ id, type }: SavedObject) { @@ -631,17 +588,6 @@ export function toAssetReference({ id, type }: SavedObject) { return reference; } -function hasReferences(assetsToInstall: SavedObjectAsset[]) { - return assetsToInstall.some((asset) => asset.references.length); -} - -async function installAlertRules({ - logger, - alertRuleAssets, -}: { - logger: Logger; - alertRuleAssets: AlertRuleAsset[]; -}): Promise { - logger.debug(`no-op alert rule assets: ${JSON.stringify(alertRuleAssets, null, 2)}`); - return Promise.resolve(); +function hasReferences(assetsToInstall: ArchiveAsset[]) { + return assetsToInstall.some((asset) => asset.references?.length); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts index da15fe5a86806..9df315427828f 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install.ts @@ -40,6 +40,7 @@ import type { InstallResult, InstallSource, InstallType, + KibanaAssetType, PackageVerificationResult, InstallResultStatus, } from '../../../types'; @@ -71,6 +72,8 @@ import { unpackBufferToAssetsMap, } from '../archive'; import { createArchiveIteratorFromMap } from '../archive/archive_iterator'; +import { toAssetReference } from '../kibana/assets/install'; +import type { ArchiveAsset } from '../kibana/assets/install'; import type { PackageUpdateEvent } from '../../upgrade_sender'; import { sendTelemetryEvents, UpdateEventType } from '../../upgrade_sender'; import { auditLoggingService } from '../../audit_logging'; @@ -1251,6 +1254,12 @@ export async function createInstallation(options: { return created; } +export const kibanaAssetsToAssetsRef = ( + kibanaAssets: Record +): KibanaAssetReference[] => { + return Object.values(kibanaAssets).flat().map(toAssetReference); +}; + export const saveKibanaAssetsRefs = async ( savedObjectsClient: SavedObjectsClientContract, pkgName: string, From 6633b5909ac42f39511322a0d786c1ae1422f645 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 10:26:47 -0700 Subject: [PATCH 27/41] Support alert rule assets as saved object --- .../services/epm/kibana/assets/install.ts | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 5d7043c90844d..eec85ef343f5a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -87,13 +87,17 @@ const AssetFilters: Record ArchiveAsse export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectToBe { // convert that to an object - const so: Partial = { + let so: Partial = { type: asset.type, id: asset.id, attributes: asset.attributes, references: asset.references || [], }; + if (asset.type === KibanaSavedObjectType.alert) { + so = fillAlertDefaults(so); + } + // migrating deprecated migrationVersion to typeMigrationVersion if (asset.migrationVersion && asset.migrationVersion[asset.type]) { so.typeMigrationVersion = asset.migrationVersion[asset.type]; @@ -591,3 +595,21 @@ export function toAssetReference({ id, type }: SavedObject) { function hasReferences(assetsToInstall: ArchiveAsset[]) { return assetsToInstall.some((asset) => asset.references?.length); } + +export function fillAlertDefaults(alertSo: Partial) { + const currentDateTime = new Date().toISOString(); + return { + ...alertSo, + attributes: { + ...(alertSo.attributes ?? {}), + enabled: false, + revision: 0, + executionStatus: { + status: 'pending', + lastExecutionDate: currentDateTime, + }, + createdAt: currentDateTime, + updatedAt: currentDateTime, + }, + }; +} From c919665a81e30f4dd37603d23eaff92c622e48c0 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 11:47:39 -0700 Subject: [PATCH 28/41] Support tags for alert assets --- .../services/epm/kibana/assets/alert.ts | 54 +++++++++++++++++ .../services/epm/kibana/assets/install.ts | 59 +++++++++++-------- .../services/epm/kibana/assets/tag_assets.ts | 5 +- 3 files changed, 91 insertions(+), 27 deletions(-) create mode 100644 x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.ts diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.ts new file mode 100644 index 0000000000000..540d1770fd964 --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.ts @@ -0,0 +1,54 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ +import type { SavedObjectToBe, InstallAssetContext } from './install'; +import { getPackageTagId, getManagedTagId } from './tag_assets'; + +export function fillAlertDefaults(alertSo: Partial, context: InstallAssetContext) { + const currentDateTime = new Date().toISOString(); + const tags = getTags(alertSo.id!, context); + const existingTags = Array.isArray((alertSo.attributes as Record).tags) + ? ((alertSo.attributes as Record).tags as string[]) + : []; + + // Based on x-pack/platform/plugins/shared/alerting/server/application/rule/methods/create/create_rule.ts + const newSo = { + ...alertSo, + attributes: { + ...(alertSo.attributes ?? {}), + enabled: false, + revision: 0, + executionStatus: { + status: 'pending', + lastExecutionDate: currentDateTime, + }, + createdAt: currentDateTime, + updatedAt: currentDateTime, + running: false, + tags: [...new Set([...existingTags, ...tags])], + }, + }; + + return newSo; +} + +function getTags(id: string, context: InstallAssetContext) { + const { pkgName, spaceId, assetTags } = context; + const tags = [getPackageTagId(spaceId, pkgName), getManagedTagId(spaceId)]; + + if (!assetTags || assetTags.length === 0) { + return tags; + } + + const filteredAssetTags = assetTags.reduce((_assetTags, assetTag) => { + if (assetTag.asset_types?.includes('alert') || assetTag.asset_ids?.includes(id)) { + return [..._assetTags, assetTag.text]; + } + return _assetTags; + }, []); + + return [...tags, ...filteredAssetTags]; +} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index eec85ef343f5a..45bc3e1226104 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -37,6 +37,7 @@ import { appContextService } from '../../..'; import { tagKibanaAssets } from './tag_assets'; import { getSpaceAwareSaveobjectsClients } from './saved_objects'; +import { fillAlertDefaults } from './alert'; const MAX_ASSETS_TO_INSTALL_IN_PARALLEL = 200; @@ -46,7 +47,7 @@ const formatImportErrorsForLog = (errors: SavedObjectsImportFailure[]) => errors.map(({ type, id, error }) => ({ type, id, error })) // discard other fields ); const validKibanaAssetTypes = new Set(Object.values(KibanaAssetType)); -type SavedObjectToBe = Required> & { +export type SavedObjectToBe = Required> & { type: KibanaSavedObjectType; }; export type ArchiveAsset = Pick< @@ -61,6 +62,12 @@ export type ArchiveAsset = Pick< type: KibanaSavedObjectType; }; +export interface InstallAssetContext { + pkgName: string; + spaceId: string; + assetTags?: PackageSpecTags[]; +} + // KibanaSavedObjectTypes are used to ensure saved objects being created for a given // KibanaAssetType have the correct type export const KibanaSavedObjectTypeMapping: Record = { @@ -85,7 +92,10 @@ const AssetFilters: Record ArchiveAsse [KibanaAssetType.indexPattern]: removeReservedIndexPatterns, }; -export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectToBe { +export function createSavedObjectKibanaAsset( + asset: ArchiveAsset, + context: InstallAssetContext +): SavedObjectToBe { // convert that to an object let so: Partial = { type: asset.type, @@ -95,7 +105,7 @@ export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectTo }; if (asset.type === KibanaSavedObjectType.alert) { - so = fillAlertDefaults(so); + so = fillAlertDefaults(so, context); } // migrating deprecated migrationVersion to typeMigrationVersion @@ -115,10 +125,11 @@ export async function installKibanaAssets(options: { savedObjectsClient: SavedObjectsClientContract; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; - pkgName: string; + context: InstallAssetContext; kibanaAssetsArchiveIterator: ReturnType; }): Promise { - const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger } = options; + const { kibanaAssetsArchiveIterator, savedObjectsClient, savedObjectsImporter, logger, context } = + options; let assetsToInstall: ArchiveAsset[] = []; let res: SavedObjectsImportSuccess[] = []; @@ -137,6 +148,7 @@ export async function installKibanaAssets(options: { logger, savedObjectsImporter, kibanaAssets: assetsToInstall, + context, assetsChunkSize: MAX_ASSETS_TO_INSTALL_IN_PARALLEL, }); assetsToInstall = []; @@ -288,11 +300,17 @@ export async function installKibanaAssetsAndReferences({ } let installedKibanaAssetsRefs: KibanaAssetReference[] = []; + const context: InstallAssetContext = { + pkgName, + spaceId, + assetTags, + }; + const importedAssets = await installKibanaAssets({ savedObjectsClient, logger, savedObjectsImporter, - pkgName, + context, kibanaAssetsArchiveIterator, }); const assets = importedAssets.map( @@ -427,10 +445,12 @@ export async function installKibanaSavedObjects({ kibanaAssets, assetsChunkSize, logger, + context, }: { kibanaAssets: ArchiveAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; + context: InstallAssetContext; assetsChunkSize?: number; }): Promise { if (!assetsChunkSize || kibanaAssets.length <= assetsChunkSize || hasReferences(kibanaAssets)) { @@ -439,6 +459,7 @@ export async function installKibanaSavedObjects({ savedObjectsImporter, kibanaAssets, refresh: 'wait_for', + context, }); } @@ -460,6 +481,7 @@ export async function installKibanaSavedObjects({ savedObjectsImporter, kibanaAssets: assetChunk, refresh: false, + context, }); installedAssets.push(...result); @@ -470,6 +492,7 @@ export async function installKibanaSavedObjects({ savedObjectsImporter, kibanaAssets: lastAssetChunk, refresh: 'wait_for', + context, }); installedAssets.push(...result); @@ -483,17 +506,21 @@ async function installKibanaSavedObjectsChunk({ kibanaAssets, logger, refresh, + context, }: { kibanaAssets: ArchiveAsset[]; savedObjectsImporter: SavedObjectsImporterContract; logger: Logger; refresh?: boolean | 'wait_for'; + context: InstallAssetContext; }) { if (!kibanaAssets.length) { return []; } - const toBeSavedObjects = kibanaAssets.map((asset) => createSavedObjectKibanaAsset(asset)); + const toBeSavedObjects = kibanaAssets.map((asset) => + createSavedObjectKibanaAsset(asset, context) + ); let allSuccessResults: SavedObjectsImportSuccess[] = []; @@ -595,21 +622,3 @@ export function toAssetReference({ id, type }: SavedObject) { function hasReferences(assetsToInstall: ArchiveAsset[]) { return assetsToInstall.some((asset) => asset.references?.length); } - -export function fillAlertDefaults(alertSo: Partial) { - const currentDateTime = new Date().toISOString(); - return { - ...alertSo, - attributes: { - ...(alertSo.attributes ?? {}), - enabled: false, - revision: 0, - executionStatus: { - status: 'pending', - lastExecutionDate: currentDateTime, - }, - createdAt: currentDateTime, - updatedAt: currentDateTime, - }, - }; -} diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts index bebc0ba9dc810..5b0e336f423af 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/tag_assets.ts @@ -55,8 +55,9 @@ const TAG_COLORS = [ '#A0A0A0', ]; -const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; -const getPackageTagId = (spaceId: string, pkgName: string) => `fleet-pkg-${pkgName}-${spaceId}`; +export const getManagedTagId = (spaceId: string) => `fleet-managed-${spaceId}`; +export const getPackageTagId = (spaceId: string, pkgName: string) => + `fleet-pkg-${pkgName}-${spaceId}`; const getLegacyPackageTagId = (pkgName: string) => pkgName; /* From 823931012f6aa8ffbf92870c0086ac12f2441a34 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 12:00:04 -0700 Subject: [PATCH 29/41] Support alert asset tagging when streaming --- .../kibana/assets/install_with_streaming.ts | 20 ++++++++++++++++--- .../steps/step_install_kibana_assets.ts | 1 + 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index b424d71b00f62..96c1794b14f75 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -8,12 +8,12 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { PackageInstallContext } from '../../../../../common/types'; -import type { KibanaAssetReference, KibanaAssetType } from '../../../../types'; +import type { KibanaAssetReference, KibanaAssetType, PackageSpecTags } from '../../../../types'; import { getPathParts } from '../../archive'; import { saveKibanaAssetsRefs } from '../../packages/install'; -import type { ArchiveAsset } from './install'; +import type { ArchiveAsset, InstallAssetContext } from './install'; import { KibanaSavedObjectTypeMapping, createSavedObjectKibanaAsset, @@ -27,6 +27,7 @@ interface InstallKibanaAssetsWithStreamingArgs { pkgName: string; packageInstallContext: PackageInstallContext; spaceId: string; + assetTags?: PackageSpecTags[]; savedObjectsClient: SavedObjectsClientContract; } @@ -36,6 +37,7 @@ export async function installKibanaAssetsWithStreaming({ spaceId, packageInstallContext, savedObjectsClient, + assetTags, pkgName, }: InstallKibanaAssetsWithStreamingArgs): Promise { const { archiveIterator } = packageInstallContext; @@ -51,6 +53,12 @@ export async function installKibanaAssetsWithStreaming({ const assetRefs: KibanaAssetReference[] = []; let batch: ArchiveAsset[] = []; + const context: InstallAssetContext = { + pkgName, + spaceId, + assetTags, + }; + await archiveIterator.traverseEntries(async ({ path, buffer }) => { if (!buffer || !isKibanaAssetType(path)) { return; @@ -69,6 +77,7 @@ export async function installKibanaAssetsWithStreaming({ await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, kibanaAssets: batch, + context, refresh: false, }); batch = []; @@ -80,6 +89,7 @@ export async function installKibanaAssetsWithStreaming({ await bulkCreateSavedObjects({ savedObjectsClient: savedObjectClientWithSpace, kibanaAssets: batch, + context, // Use wait_for with the last batch to ensure all assets are readable once the install is complete refresh: 'wait_for', }); @@ -95,16 +105,20 @@ async function bulkCreateSavedObjects({ savedObjectsClient, kibanaAssets, refresh, + context, }: { kibanaAssets: ArchiveAsset[]; savedObjectsClient: SavedObjectsClientContract; refresh?: boolean | 'wait_for'; + context: InstallAssetContext; }) { if (!kibanaAssets.length) { return []; } - const toBeSavedObjects = kibanaAssets.map((asset) => createSavedObjectKibanaAsset(asset)); + const toBeSavedObjects = kibanaAssets.map((asset) => + createSavedObjectKibanaAsset(asset, context) + ); const { saved_objects: createdSavedObjects } = await savedObjectsClient.bulkCreate( toBeSavedObjects, diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts index ba8f71123eb6d..70a643259abe0 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/install_state_machine/steps/step_install_kibana_assets.ts @@ -52,6 +52,7 @@ export async function stepInstallKibanaAssetsWithStreaming(context: InstallConte pkgName, packageInstallContext, spaceId, + assetTags: packageInfo?.asset_tags, }) ); From 2d216558fe9224c5de0d0af7f2e2c4882c8bd3ce Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 12:34:35 -0700 Subject: [PATCH 30/41] Include alert hidden type in SO client getters --- .../plugins/shared/fleet/server/services/app_context.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts index 52c35739d2208..019bd137f2ae9 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/app_context.ts @@ -224,7 +224,7 @@ class AppContextService { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(request, { - includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, KibanaSavedObjectType.alert], excludedExtensions: [SECURITY_EXTENSION_ID], }); } @@ -243,7 +243,7 @@ class AppContextService { // soClient as kibana internal users, be careful on how you use it, security is not enabled return appContextService.getSavedObjects().getScopedClient(fakeRequest, { excludedExtensions: [SECURITY_EXTENSION_ID, SPACES_EXTENSION_ID], - includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE], + includedHiddenTypes: [UNINSTALL_TOKENS_SAVED_OBJECT_TYPE, KibanaSavedObjectType.alert], }); } From 0745b8510ca477cb2c11690d72c07d4fd6d49062 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 13:00:08 -0700 Subject: [PATCH 31/41] Fix type issues --- .../context/fixtures/integration.nginx.ts | 1 + .../.storybook/context/fixtures/integration.okta.ts | 1 + .../shared/fleet/server/routes/epm/index.test.ts | 1 + .../services/epm/kibana/assets/install.test.ts | 13 +++++++++++-- .../view/ingest_manager_integration/mocks.tsx | 2 ++ 5 files changed, 16 insertions(+), 2 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts index ea89331156566..5f246f60f7319 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.nginx.ts @@ -57,6 +57,7 @@ export const item: GetInfoResponse['item'] = { ], assets: { kibana: { + alert: [], dashboard: [ { pkgkey: 'nginx-0.7.0', diff --git a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts index ddae02803faf0..bc4be53b4d386 100644 --- a/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts +++ b/x-pack/platform/plugins/shared/fleet/.storybook/context/fixtures/integration.okta.ts @@ -43,6 +43,7 @@ export const item: GetInfoResponse['item'] = { ], assets: { kibana: { + alert: [], dashboard: [ { pkgkey: 'okta-1.2.0', diff --git a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts index 96e25bfdc8c2a..2822b8c1b90f0 100644 --- a/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/routes/epm/index.test.ts @@ -189,6 +189,7 @@ describe('schema validation', () => { }; const assets: AssetsGroupedByServiceByType = { kibana: { + alert: [], dashboard: [], visualization: [], search: [], diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts index 3b200ac5115cf..6622e4c246414 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.test.ts @@ -46,6 +46,11 @@ const createImportResponse = ( successCount: successResults.length, } as SavedObjectsImportResponse); +const mockInstallAssetContext = { + pkgName: 'Mock package', + spaceId: 'default', +}; + describe('installKibanaSavedObjects', () => { beforeEach(() => { mockImporter.import.mockReset(); @@ -65,6 +70,7 @@ describe('installKibanaSavedObjects', () => { savedObjectsImporter: mockImporter, logger: mockLogger, kibanaAssets: [asset], + context: mockInstallAssetContext, }); expect(mockImporter.import).toHaveBeenCalledTimes(2); @@ -81,6 +87,7 @@ describe('installKibanaSavedObjects', () => { savedObjectsImporter: mockImporter, logger: mockLogger, kibanaAssets: [asset], + context: mockInstallAssetContext, }) ).rejects.toEqual(expect.any(Error)); expect(mockImporter.import).toHaveBeenCalledTimes(51); @@ -97,6 +104,7 @@ describe('installKibanaSavedObjects', () => { savedObjectsImporter: mockImporter, logger: mockLogger, kibanaAssets: [asset], + context: mockInstallAssetContext, }) ).rejects.toEqual(expect.any(Error)); }); @@ -115,6 +123,7 @@ describe('installKibanaSavedObjects', () => { savedObjectsImporter: mockImporter, logger: mockLogger, kibanaAssets: [asset], + context: mockInstallAssetContext, }); expect(mockImporter.import).toHaveBeenCalledTimes(1); @@ -128,7 +137,7 @@ describe('createSavedObjectKibanaAsset', () => { attributes: { hello: 'world' }, migrationVersion: { dashboard: '8.6.0' }, }); - const result = createSavedObjectKibanaAsset(asset); + const result = createSavedObjectKibanaAsset(asset, mockInstallAssetContext); expect(result.typeMigrationVersion).toEqual('8.6.0'); }); @@ -139,7 +148,7 @@ describe('createSavedObjectKibanaAsset', () => { typeMigrationVersion: '8.6.0', coreMigrationVersion: '8.7.0', }); - const result = createSavedObjectKibanaAsset(asset); + const result = createSavedObjectKibanaAsset(asset, mockInstallAssetContext); expect(result.typeMigrationVersion).toEqual('8.6.0'); expect(result.coreMigrationVersion).toEqual('8.7.0'); diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx index e61ea3341bc53..bccd333a646ba 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx @@ -64,6 +64,7 @@ export const createFleetContextRendererMock = (): AppContextTestRender => { const mockedContext = createAppRootMockRenderer(); const { coreStart, depsStart, queryClient, startServices } = mockedContext; + // @ts-expect-error TS2589 const store = createFleetContextReduxStore({ coreStart, depsStart, @@ -162,6 +163,7 @@ export const generateFleetPackageInfo = (): PackageInfo => { path: '', assets: { kibana: { + alert: [], csp_rule_template: [], dashboard: [], visualization: [], From 59b507c613e938b4448b6db4ba532be9fa0b8f68 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 14:02:20 -0700 Subject: [PATCH 32/41] Support alert deletions on package uninstall --- .../shared/fleet/server/services/epm/packages/remove.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 18b5fe75d9961..507d5dad0dee4 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -28,7 +28,7 @@ import { SO_SEARCH_LIMIT, USER_SETTINGS_TEMPLATE_SUFFIX, } from '../../../constants'; -import { ElasticsearchAssetType } from '../../../types'; +import { ElasticsearchAssetType, KibanaSavedObjectType } from '../../../types'; import type { AssetReference, AssetType, @@ -154,7 +154,7 @@ export async function deleteKibanaAssets({ spaceId?: string; }) { const savedObjectsClient = new SavedObjectsClient( - appContextService.getSavedObjects().createInternalRepository() + appContextService.getSavedObjects().createInternalRepository([KibanaSavedObjectType.alert]) ); const namespace = SavedObjectsUtils.namespaceStringToId(spaceId); @@ -331,6 +331,7 @@ export async function deletePrerequisiteAssets( concurrency: MAX_CONCURRENT_ES_ASSETS_OPERATIONS, }); } catch (err) { + logger.debug(`Deletion error: ${err}`); // in the rollback case, partial installs are likely, so missing assets are not an error if (!SavedObjectsErrorHelpers.isNotFoundError(err)) { logger.error(err); @@ -447,7 +448,6 @@ export async function deleteKibanaSavedObjectsAssets({ const assetsToDelete = refsToDelete .filter(({ type }) => kibanaSavedObjectTypes.includes(type)) .map(({ id, type }) => ({ id, type } as KibanaAssetReference)); - try { const packageInfo = await getPackageInfo({ savedObjectsClient, @@ -463,6 +463,7 @@ export async function deleteKibanaSavedObjectsAssets({ logger, }); } catch (err) { + logger.debug(`Deletion error: ${err}`); // in the rollback case, partial installs are likely, so missing assets are not an error if (!SavedObjectsErrorHelpers.isNotFoundError(err)) { logger.error(err); From 282e9f89d2ce7f51d4810f40612963e1890c8995 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Thu, 17 Jul 2025 15:08:38 -0700 Subject: [PATCH 33/41] Add tests for fillAlertDefaults --- .../services/epm/kibana/assets/alert.test.ts | 100 ++++++++++++++++++ .../server/services/epm/packages/remove.ts | 1 - 2 files changed, 100 insertions(+), 1 deletion(-) create mode 100644 x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.test.ts diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.test.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.test.ts new file mode 100644 index 0000000000000..279c3c4219ae7 --- /dev/null +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/alert.test.ts @@ -0,0 +1,100 @@ +/* + * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one + * or more contributor license agreements. Licensed under the Elastic License + * 2.0; you may not use this file except in compliance with the Elastic License + * 2.0. + */ + +import { KibanaSavedObjectType } from '../../../../types'; + +import { fillAlertDefaults } from './alert'; + +describe('fillAlertDefaults', () => { + it('should fill in default values for alert saved object', () => { + const alertSo = { + id: 'test-alert', + type: KibanaSavedObjectType.alert, + attributes: { + name: 'Test Alert', + }, + executionStatus: { + status: 'ok', + lastExecutionDate: '2023-10-01T00:00:00Z', + }, + }; + + const context = { + pkgName: 'test-package', + spaceId: 'default', + assetTags: [], + }; + + const result = fillAlertDefaults(alertSo, context); + + expect(result.id).toBe('test-alert'); + expect((result.attributes as Record).name).toBe('Test Alert'); + expect(result.attributes.enabled).toBe(false); + expect(result.attributes.revision).toBe(0); + expect(result.attributes.executionStatus.status).toBe('pending'); + expect(result.attributes.createdAt).toBeDefined(); + expect(result.attributes.updatedAt).toBeDefined(); + expect(result.attributes.running).toBe(false); + expect(result.attributes.tags).toEqual([ + 'fleet-pkg-test-package-default', + 'fleet-managed-default', + ]); + }); + it('should include existing tags with default tags', () => { + const alertSo = { + id: 'test-alert', + type: KibanaSavedObjectType.alert, + attributes: { + name: 'Test Alert', + tags: ['existing-tag'], + }, + }; + + const context = { + pkgName: 'test-package', + spaceId: 'default', + assetTags: [], + }; + + const result = fillAlertDefaults(alertSo, context); + + expect(result.attributes.tags).toEqual([ + 'existing-tag', + 'fleet-pkg-test-package-default', + 'fleet-managed-default', + ]); + }); + it('should include tags from assetTags if they match', () => { + const alertSo = { + id: 'test-alert', + type: KibanaSavedObjectType.alert, + attributes: { + name: 'Test Alert', + }, + }; + + const context = { + pkgName: 'test-package', + spaceId: 'default', + assetTags: [ + { text: 'alert-specific-tag', asset_types: ['alert'] }, + { text: 'other-asset-tag', asset_types: ['dashboard'] }, + { text: 'id-specific-tag', asset_ids: ['test-alert'] }, + { text: 'not-matching-id-tag', asset_ids: ['other-alert'] }, + ], + }; + + const result = fillAlertDefaults(alertSo, context); + + expect(result.attributes.tags).toEqual([ + 'fleet-pkg-test-package-default', + 'fleet-managed-default', + 'alert-specific-tag', + 'id-specific-tag', + ]); + }); +}); diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts index 507d5dad0dee4..2b6fb6e09334a 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/packages/remove.ts @@ -331,7 +331,6 @@ export async function deletePrerequisiteAssets( concurrency: MAX_CONCURRENT_ES_ASSETS_OPERATIONS, }); } catch (err) { - logger.debug(`Deletion error: ${err}`); // in the rollback case, partial installs are likely, so missing assets are not an error if (!SavedObjectsErrorHelpers.isNotFoundError(err)) { logger.error(err); From 586f7c18ab2bad46f00e626cc1c4e2f0af85512d Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Fri, 18 Jul 2025 09:03:00 -0700 Subject: [PATCH 34/41] Update FTR tests --- .../epm/__snapshots__/bulk_get_assets.snap | 6 ++++ .../apis/epm/install_remove_assets.ts | 9 ++++++ .../apis/epm/update_assets.ts | 9 ++++++ .../0.1.0/kibana/alert/sample_alert_rule.json | 29 +++++++++++++++++++ .../0.2.0/kibana/alert/sample_alert_rule.json | 29 +++++++++++++++++++ 5 files changed, 82 insertions(+) create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json create mode 100644 x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json diff --git a/x-pack/platform/test/fleet_api_integration/apis/epm/__snapshots__/bulk_get_assets.snap b/x-pack/platform/test/fleet_api_integration/apis/epm/__snapshots__/bulk_get_assets.snap index de1e6ab8880d7..ae433ed21c8db 100644 --- a/x-pack/platform/test/fleet_api_integration/apis/epm/__snapshots__/bulk_get_assets.snap +++ b/x-pack/platform/test/fleet_api_integration/apis/epm/__snapshots__/bulk_get_assets.snap @@ -104,6 +104,12 @@ Array [ "id": "metrics-all_assets.test_metrics@custom", "type": "component_template", }, + Object { + "appLink": "", + "attributes": Object {}, + "id": "sample_alert_rule", + "type": "alert", + }, Object { "appLink": "", "attributes": Object {}, diff --git a/x-pack/platform/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/platform/test/fleet_api_integration/apis/epm/install_remove_assets.ts index 64fb4904023f5..117c84ab2ed3b 100644 --- a/x-pack/platform/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/platform/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -562,6 +562,10 @@ const expectAssetsInstalled = ({ expect(sortedRes).eql({ installed_kibana: [ + { + id: 'sample_alert_rule', + type: 'alert', + }, { id: 'sample_csp_rule_template', type: 'csp-rule-template', @@ -757,6 +761,11 @@ const expectAssetsInstalled = ({ path: 'all_assets-0.1.0/img/logo_overrides_64_color.svg', type: 'epm-packages-assets', }, + { + id: 'af688395-0e06-5c7f-9584-05ffba778108', + path: 'all_assets-0.1.0/kibana/alert/sample_alert_rule.json', + type: 'epm-packages-assets', + }, { id: '943d5767-41f5-57c3-ba02-48e0f6a837db', path: 'all_assets-0.1.0/kibana/csp_rule_template/sample_csp_rule_template.json', diff --git a/x-pack/platform/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/platform/test/fleet_api_integration/apis/epm/update_assets.ts index d22e605880b31..733967edda153 100644 --- a/x-pack/platform/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/platform/test/fleet_api_integration/apis/epm/update_assets.ts @@ -345,6 +345,10 @@ export default function (providerContext: FtrProviderContext) { installed_kibana_space_id: 'default', installed_kibana: sortBy( [ + { + id: 'sample_alert_rule', + type: 'alert', + }, { id: 'sample_dashboard', type: 'dashboard', @@ -556,6 +560,11 @@ export default function (providerContext: FtrProviderContext) { path: 'all_assets-0.2.0/kibana/csp_rule_template/sample_csp_rule_template.json', type: 'epm-packages-assets', }, + { + id: '81cb1738-dcfc-5d22-8367-d13f4b5908a5', + path: 'all_assets-0.2.0/kibana/alert/sample_alert_rule.json', + type: 'epm-packages-assets', + }, { id: '848d7b69-26d1-52c1-8afc-65e627b34812', path: 'all_assets-0.2.0/kibana/security_ai_prompt/sample_security_ai_prompts.json', diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json new file mode 100644 index 0000000000000..5243a8fcd56d6 --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json @@ -0,0 +1,29 @@ +{ + "id": "sample_alert_rule", + "type": "alert", + "attributes": { + "name": "Sample alert rule", + "tags": ["Testing"], + "enabled": false, + "alertTypeId": "apm.anomaly", + "consumer": "alerts", + "schedule": { + "interval": "1m" + }, + "params": { + "windowSize": 30, + "windowUnit": "m", + "anomalySeverityType": "critical", + "anomalyDetectorTypes": ["txLatency", "txThroughput", "txFailureRate"], + "environment": "ENVIRONMENT_ALL" + }, + "muteAll": false, + "mutedInstanceIds": [], + "alertDelay": { + "active": 1 + }, + "actions": [] + }, + "coreMigrationVersion": "8.8.0", + "typeMigrationVersion": "10.6.0" +} diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json new file mode 100644 index 0000000000000..66ec64117e69f --- /dev/null +++ b/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json @@ -0,0 +1,29 @@ +{ + "id": "sample_alert_rule", + "type": "alert", + "attributes": { + "name": "Sample alert rule v2", + "tags": ["Testing"], + "enabled": false, + "alertTypeId": "apm.anomaly", + "consumer": "alerts", + "schedule": { + "interval": "1m" + }, + "params": { + "windowSize": 30, + "windowUnit": "m", + "anomalySeverityType": "critical", + "anomalyDetectorTypes": ["txLatency", "txThroughput", "txFailureRate"], + "environment": "ENVIRONMENT_ALL" + }, + "muteAll": false, + "mutedInstanceIds": [], + "alertDelay": { + "active": 1 + }, + "actions": [] + }, + "coreMigrationVersion": "8.8.0", + "typeMigrationVersion": "10.6.0" +} From 0019f77cfebfd7bed34ed464c54bea9b4fd85c3c Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Fri, 18 Jul 2025 10:37:24 -0700 Subject: [PATCH 35/41] Cleanup file move from incorporating main --- .../all_assets/0.1.0/kibana/alert/sample_alert_rule.json | 0 .../all_assets/0.2.0/kibana/alert/sample_alert_rule.json | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename x-pack/{ => platform}/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json (100%) rename x-pack/{ => platform}/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json (100%) diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json b/x-pack/platform/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json similarity index 100% rename from x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json rename to x-pack/platform/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.1.0/kibana/alert/sample_alert_rule.json diff --git a/x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json b/x-pack/platform/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json similarity index 100% rename from x-pack/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json rename to x-pack/platform/test/fleet_api_integration/apis/fixtures/test_packages/all_assets/0.2.0/kibana/alert/sample_alert_rule.json From 1d073454ad1e901a39a11085672503c9a4e1533d Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Fri, 18 Jul 2025 18:04:18 +0000 Subject: [PATCH 36/41] [CI] Auto-commit changed files from 'node scripts/yarn_deduplicate' --- x-pack/platform/plugins/shared/fleet/tsconfig.json | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/fleet/tsconfig.json b/x-pack/platform/plugins/shared/fleet/tsconfig.json index 556e1262be0dc..213cff586ad33 100644 --- a/x-pack/platform/plugins/shared/fleet/tsconfig.json +++ b/x-pack/platform/plugins/shared/fleet/tsconfig.json @@ -122,6 +122,5 @@ "@kbn/logs-data-access-plugin", "@kbn/embeddable-plugin", "@kbn/core-chrome-layout-constants", - "@kbn/alerting-plugin" ] } From cd0d8fddcc87f1c3de1da894508f2b7ef7839019 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Fri, 18 Jul 2025 12:01:29 -0700 Subject: [PATCH 37/41] Remove unused ts-ignore rule --- .../pages/policy/view/ingest_manager_integration/mocks.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx index bccd333a646ba..8ec4bbfaa60f1 100644 --- a/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx +++ b/x-pack/solutions/security/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/mocks.tsx @@ -64,7 +64,6 @@ export const createFleetContextRendererMock = (): AppContextTestRender => { const mockedContext = createAppRootMockRenderer(); const { coreStart, depsStart, queryClient, startServices } = mockedContext; - // @ts-expect-error TS2589 const store = createFleetContextReduxStore({ coreStart, depsStart, From a07e446f78852f37cdbb397b14e619b884302396 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Mon, 28 Jul 2025 11:05:51 -0700 Subject: [PATCH 38/41] Put alert asset install behind feature flag enableAlertRuleTemplateSupport --- .../shared/fleet/common/experimental_features.ts | 1 + .../server/services/epm/kibana/assets/install.ts | 7 +++++++ .../epm/kibana/assets/install_with_streaming.ts | 15 ++++++++++++++- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts b/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts index 424ad7c87a7e8..c5e8b1fc98a13 100644 --- a/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts +++ b/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts @@ -18,6 +18,7 @@ const _allowedExperimentalValues = { enableAgentMigrations: false, enablePackageRollback: false, enableAutoInstallContentPackages: false, + enableAlertRuleTemplateSupport: false, }; /** diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index 45bc3e1226104..b5e36f62ea945 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -399,6 +399,13 @@ function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallCon return; } + if ( + soType === KibanaSavedObjectType.alert && + !appContextService.getExperimentalFeatures().enableAlertRuleTemplateSupport + ) { + return; + } + if (asset.type === soType) { await onEntry({ path: entry.path, assetType, asset }); } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index 96c1794b14f75..15741054b27c1 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -8,8 +8,14 @@ import type { SavedObjectsClientContract } from '@kbn/core/server'; import type { PackageInstallContext } from '../../../../../common/types'; -import type { KibanaAssetReference, KibanaAssetType, PackageSpecTags } from '../../../../types'; +import { + KibanaSavedObjectType, + type KibanaAssetReference, + type KibanaAssetType, + type PackageSpecTags, +} from '../../../../types'; import { getPathParts } from '../../archive'; +import { appContextService } from '../../../app_context'; import { saveKibanaAssetsRefs } from '../../packages/install'; @@ -70,6 +76,13 @@ export async function installKibanaAssetsWithStreaming({ return; } + if ( + soType === KibanaSavedObjectType.alert && + !appContextService.getExperimentalFeatures().enableAlertRuleTemplateSupport + ) { + return; + } + batch.push(savedObject); assetRefs.push(toAssetReference(savedObject)); From 6b9f732703f3c7391b872d3bbbbea1e6fbbdb743 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Mon, 28 Jul 2025 12:06:24 -0700 Subject: [PATCH 39/41] Add alert template feature flag to FTR tests --- .../platform/test/fleet_api_integration/config.epm.ts | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/x-pack/platform/test/fleet_api_integration/config.epm.ts b/x-pack/platform/test/fleet_api_integration/config.epm.ts index 1e9132a4e60d3..0f5fffb339eff 100644 --- a/x-pack/platform/test/fleet_api_integration/config.epm.ts +++ b/x-pack/platform/test/fleet_api_integration/config.epm.ts @@ -9,9 +9,20 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const baseFleetApiConfig = await readConfigFile(require.resolve('./config.base.ts')); + const serverArgs: string[] = [...baseFleetApiConfig.get('kbnTestServer.serverArgs')]; + const enableExperimentalIndex = serverArgs.findIndex((val) => + val.includes('xpack.fleet.enableExperimental') + ); + serverArgs[enableExperimentalIndex] = `--xpack.fleet.enableExperimental=${JSON.stringify([ + 'enableAlertRuleTemplateSupport', + ])}`; return { ...baseFleetApiConfig.getAll(), + kbnTestServer: { + ...baseFleetApiConfig.get('kbnTestServer'), + serverArgs, + }, testFiles: [require.resolve('./apis/epm')], junit: { reportName: 'X-Pack EPM API Integration Tests', From 47d35873357504dbde5f5d8761da1afaa615257b Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Tue, 29 Jul 2025 08:30:26 -0700 Subject: [PATCH 40/41] Move inclusion of rule asset flag to base FTR config --- .../test/fleet_api_integration/config.base.ts | 1 + .../platform/test/fleet_api_integration/config.epm.ts | 11 ----------- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/x-pack/platform/test/fleet_api_integration/config.base.ts b/x-pack/platform/test/fleet_api_integration/config.base.ts index aced226394abb..c32e5807530c4 100644 --- a/x-pack/platform/test/fleet_api_integration/config.base.ts +++ b/x-pack/platform/test/fleet_api_integration/config.base.ts @@ -90,6 +90,7 @@ export default async function ({ readConfigFile, log }: FtrConfigProviderContext 'enableAutomaticAgentUpgrades', 'enableAgentMigrations', 'enablePackageRollback', + 'enableAlertRuleTemplateSupport', ])}`, `--xpack.cloud.id='123456789'`, `--xpack.fleet.agentless.enabled=true`, diff --git a/x-pack/platform/test/fleet_api_integration/config.epm.ts b/x-pack/platform/test/fleet_api_integration/config.epm.ts index 0f5fffb339eff..1e9132a4e60d3 100644 --- a/x-pack/platform/test/fleet_api_integration/config.epm.ts +++ b/x-pack/platform/test/fleet_api_integration/config.epm.ts @@ -9,20 +9,9 @@ import { FtrConfigProviderContext } from '@kbn/test'; export default async function ({ readConfigFile }: FtrConfigProviderContext) { const baseFleetApiConfig = await readConfigFile(require.resolve('./config.base.ts')); - const serverArgs: string[] = [...baseFleetApiConfig.get('kbnTestServer.serverArgs')]; - const enableExperimentalIndex = serverArgs.findIndex((val) => - val.includes('xpack.fleet.enableExperimental') - ); - serverArgs[enableExperimentalIndex] = `--xpack.fleet.enableExperimental=${JSON.stringify([ - 'enableAlertRuleTemplateSupport', - ])}`; return { ...baseFleetApiConfig.getAll(), - kbnTestServer: { - ...baseFleetApiConfig.get('kbnTestServer'), - serverArgs, - }, testFiles: [require.resolve('./apis/epm')], junit: { reportName: 'X-Pack EPM API Integration Tests', From 41ac90a4f828835f4964ca853c4ddaa96dab0cd6 Mon Sep 17 00:00:00 2001 From: MichelLosier Date: Wed, 30 Jul 2025 08:52:02 -0700 Subject: [PATCH 41/41] Update flag name --- .../plugins/shared/fleet/common/experimental_features.ts | 2 +- .../shared/fleet/server/services/epm/kibana/assets/install.ts | 2 +- .../server/services/epm/kibana/assets/install_with_streaming.ts | 2 +- x-pack/platform/test/fleet_api_integration/config.base.ts | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts b/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts index c5e8b1fc98a13..cd28e7d71b8ff 100644 --- a/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts +++ b/x-pack/platform/plugins/shared/fleet/common/experimental_features.ts @@ -18,7 +18,7 @@ const _allowedExperimentalValues = { enableAgentMigrations: false, enablePackageRollback: false, enableAutoInstallContentPackages: false, - enableAlertRuleTemplateSupport: false, + enableAgentStatusAlerting: false, }; /** diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts index b5e36f62ea945..5b8e4069de1ea 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install.ts @@ -401,7 +401,7 @@ function getKibanaAssetsArchiveIterator(packageInstallContext: PackageInstallCon if ( soType === KibanaSavedObjectType.alert && - !appContextService.getExperimentalFeatures().enableAlertRuleTemplateSupport + !appContextService.getExperimentalFeatures().enableAgentStatusAlerting ) { return; } diff --git a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts index 15741054b27c1..26c23a176ea9b 100644 --- a/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts +++ b/x-pack/platform/plugins/shared/fleet/server/services/epm/kibana/assets/install_with_streaming.ts @@ -78,7 +78,7 @@ export async function installKibanaAssetsWithStreaming({ if ( soType === KibanaSavedObjectType.alert && - !appContextService.getExperimentalFeatures().enableAlertRuleTemplateSupport + !appContextService.getExperimentalFeatures().enableAgentStatusAlerting ) { return; } diff --git a/x-pack/platform/test/fleet_api_integration/config.base.ts b/x-pack/platform/test/fleet_api_integration/config.base.ts index c32e5807530c4..7a7d63a014955 100644 --- a/x-pack/platform/test/fleet_api_integration/config.base.ts +++ b/x-pack/platform/test/fleet_api_integration/config.base.ts @@ -90,7 +90,7 @@ export default async function ({ readConfigFile, log }: FtrConfigProviderContext 'enableAutomaticAgentUpgrades', 'enableAgentMigrations', 'enablePackageRollback', - 'enableAlertRuleTemplateSupport', + 'enableAgentStatusAlerting', ])}`, `--xpack.cloud.id='123456789'`, `--xpack.fleet.agentless.enabled=true`,