Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SLOs][Fleet] Install integration SLO assets #186974

Open
wants to merge 20 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,7 @@ export const item: GetInfoResponse['item'] = {
tag: [],
osquery_pack_asset: [],
osquery_saved_query: [],
slo: [],
},
elasticsearch: {
ingest_pipeline: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export const item: GetInfoResponse['item'] = {
security_rule: [],
csp_rule_template: [],
tag: [],
slo: [],
},
elasticsearch: {
ingest_pipeline: [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ describe('Fleet - packageToPackagePolicy', () => {
tag: [],
osquery_pack_asset: [],
osquery_saved_query: [],
slo: [],
},
elasticsearch: {
ingest_pipeline: [],
Expand Down
2 changes: 2 additions & 0 deletions x-pack/plugins/fleet/common/types/models/epm.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ export enum KibanaAssetType {
osqueryPackAsset = 'osquery_pack_asset',
osquerySavedQuery = 'osquery_saved_query',
tag = 'tag',
slo = 'slo',
}

/*
Expand All @@ -82,6 +83,7 @@ export enum KibanaSavedObjectType {
osqueryPackAsset = 'osquery-pack-asset',
osquerySavedQuery = 'osquery-saved-query',
tag = 'tag',
slo = 'slo',
}

export enum ElasticsearchAssetType {
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/kibana.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"telemetry",
"discover",
"ingestPipelines",
"slo",
shahzad31 marked this conversation as resolved.
Show resolved Hide resolved
"spaces",
"guidedOnboarding",
"integrationAssistant",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@ export const AssetTitleMap: Record<
osquery_saved_query: i18n.translate('xpack.fleet.epm.assetTitles.osquerySavedQuery', {
defaultMessage: 'Osquery saved queries',
}),
slo: i18n.translate('xpack.fleet.epm.assetTitles.slos', {
defaultMessage: 'SLOs',
}),

// ES
ilm_policy: i18n.translate('xpack.fleet.epm.assetTitles.ilmPolicies', {
Expand Down
6 changes: 6 additions & 0 deletions x-pack/plugins/fleet/server/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,8 @@ import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/

import { SECURITY_EXTENSION_ID } from '@kbn/core-saved-objects-server';

import type { SLOPluginSetup, SLOPluginStart } from '@kbn/slo-plugin/server/plugin';

import type { FleetConfigType } from '../common/types';
import type { FleetAuthz } from '../common';
import {
Expand Down Expand Up @@ -143,6 +145,7 @@ export interface FleetSetupDeps {
telemetry?: TelemetryPluginSetup;
taskManager: TaskManagerSetupContract;
fieldsMetadata: FieldsMetadataServerSetup;
slo?: SLOPluginSetup;
}

export interface FleetStartDeps {
Expand All @@ -153,6 +156,7 @@ export interface FleetStartDeps {
telemetry?: TelemetryPluginStart;
savedObjectsTagging: SavedObjectTaggingStart;
taskManager: TaskManagerStartContract;
slo?: SLOPluginStart;
spaces: SpacesPluginStart;
}

Expand Down Expand Up @@ -181,6 +185,7 @@ export interface FleetAppContext {
messageSigningService: MessageSigningServiceInterface;
auditLogger?: AuditLogger;
uninstallTokenService: UninstallTokenServiceInterface;
sloStart?: SLOPluginStart;
unenrollInactiveAgentsTask: UnenrollInactiveAgentsTask;
taskManagerStart?: TaskManagerStartContract;
}
Expand Down Expand Up @@ -659,6 +664,7 @@ export class FleetPlugin
bulkActionsResolver: this.bulkActionsResolver!,
messageSigningService,
uninstallTokenService,
sloStart: plugins.slo,
unenrollInactiveAgentsTask: this.unenrollInactiveAgentsTask!,
taskManagerStart: plugins.taskManager,
});
Expand Down
1 change: 1 addition & 0 deletions x-pack/plugins/fleet/server/routes/epm/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -384,6 +384,7 @@ export const createCustomIntegrationHandler: FleetRequestHandler<
force,
authorizationHeader,
kibanaVersion,
sloClient: appContextService.getSloStart()?.sloClient,
});

if (!res.error) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ export const installPackageKibanaAssetsHandler: FleetRequestHandler<
const { packageInfo } = installedPkgWithAssets;

await installKibanaAssetsAndReferences({
esClient: appContextService.getInternalUserESClient(),
savedObjectsClient,
logger,
pkgName,
Expand Down
8 changes: 8 additions & 0 deletions x-pack/plugins/fleet/server/services/app_context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ import type { SavedObjectTaggingStart } from '@kbn/saved-objects-tagging-plugin/
import { SECURITY_EXTENSION_ID, SPACES_EXTENSION_ID } from '@kbn/core-saved-objects-server';
import type { TaskManagerStartContract } from '@kbn/task-manager-plugin/server';

import type { SLOPluginStart } from '@kbn/slo-plugin/server/plugin';

import type { FleetConfigType } from '../../common/types';
import {
allowedExperimentalValues,
Expand Down Expand Up @@ -83,6 +85,7 @@ class AppContextService {
private messageSigningService: MessageSigningServiceInterface | undefined;
private uninstallTokenService: UninstallTokenServiceInterface | undefined;
private taskManagerStart: TaskManagerStartContract | undefined;
private sloStart: SLOPluginStart | undefined;

public start(appContext: FleetAppContext) {
this.data = appContext.data;
Expand All @@ -108,6 +111,7 @@ class AppContextService {
this.messageSigningService = appContext.messageSigningService;
this.uninstallTokenService = appContext.uninstallTokenService;
this.taskManagerStart = appContext.taskManagerStart;
this.sloStart = appContext.sloStart;

if (appContext.config$) {
this.config$ = appContext.config$;
Expand Down Expand Up @@ -155,6 +159,10 @@ class AppContextService {
return this.cloud;
}

public getSloStart() {
return this.sloStart;
}

public getLogger() {
if (!this.logger) {
throw new Error('Logger not set.');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ import type {
import { createListStream } from '@kbn/utils';
import { partition, chunk } from 'lodash';

import type { SLOClient } from '@kbn/slo-plugin/server/services/slo_client';

import type { ElasticsearchClient } from '@kbn/core/server';

import type { CreateSLOParams } from '@kbn/slo-schema';

import { appContextService } from '../../..';

import { getAssetFromAssetsMap, getPathParts } from '../../archive';
import { KibanaAssetType, KibanaSavedObjectType } from '../../../../types';
import type { AssetReference, Installation, PackageSpecTags } from '../../../../types';
Expand Down Expand Up @@ -75,6 +83,7 @@ export const KibanaSavedObjectTypeMapping: Record<KibanaAssetType, KibanaSavedOb
[KibanaAssetType.tag]: KibanaSavedObjectType.tag,
[KibanaAssetType.osqueryPackAsset]: KibanaSavedObjectType.osqueryPackAsset,
[KibanaAssetType.osquerySavedQuery]: KibanaSavedObjectType.osquerySavedQuery,
[KibanaAssetType.slo]: KibanaSavedObjectType.slo,
};

const AssetFilters: Record<string, (kibanaAssets: ArchiveAsset[]) => ArchiveAsset[]> = {
Expand Down Expand Up @@ -104,13 +113,17 @@ export function createSavedObjectKibanaAsset(asset: ArchiveAsset): SavedObjectTo
}

export async function installKibanaAssets(options: {
savedObjectsClient: SavedObjectsClientContract;
soClient: SavedObjectsClientContract;
savedObjectsImporter: SavedObjectsImporterContract;
logger: Logger;
pkgName: string;
kibanaAssets: Record<KibanaAssetType, ArchiveAsset[]>;
sloClient?: SLOClient;
spaceId: string;
esClient: ElasticsearchClient;
}): Promise<SavedObjectsImportSuccess[]> {
const { kibanaAssets, savedObjectsClient, savedObjectsImporter, logger } = options;
const { kibanaAssets, soClient, esClient, savedObjectsImporter, logger, sloClient, spaceId } =
options;

const assetsToInstall = Object.entries(kibanaAssets).flatMap(([assetType, assets]) => {
if (!validKibanaAssetTypes.has(assetType as KibanaAssetType)) {
Expand Down Expand Up @@ -144,7 +157,7 @@ export async function installKibanaAssets(options: {
managed: true,
});

await makeManagedIndexPatternsGlobal(savedObjectsClient);
await makeManagedIndexPatternsGlobal(soClient);

let installedAssets: SavedObjectsImportSuccess[] = [];

Expand All @@ -170,11 +183,21 @@ export async function installKibanaAssets(options: {
installedAssets = await installKibanaSavedObjects({
logger,
savedObjectsImporter,
kibanaAssets: assetsToInstall,
kibanaAssets: assetsToInstall.filter((asset) => asset.type !== KibanaSavedObjectType.slo),
});
}

return installedAssets;
const sloAssets = assetsToInstall.filter((asset) => asset.type === KibanaSavedObjectType.slo);

const installedSlos = await installSLOAssets({
sloAssets,
sloClient,
soClient,
esClient,
spaceId,
});

return installedAssets.concat(installedSlos);
}

export async function installKibanaAssetsAndReferencesMultispace({
Expand All @@ -186,6 +209,8 @@ export async function installKibanaAssetsAndReferencesMultispace({
installedPkg,
spaceId,
assetTags,
esClient,
sloClient,
installAsAdditionalSpace,
}: {
savedObjectsClient: SavedObjectsClientContract;
Expand All @@ -197,6 +222,8 @@ export async function installKibanaAssetsAndReferencesMultispace({
spaceId: string;
assetTags?: PackageSpecTags[];
installAsAdditionalSpace?: boolean;
esClient: ElasticsearchClient;
sloClient?: SLOClient;
}) {
if (installedPkg && !installAsAdditionalSpace) {
// Install in every space => upgrades
Expand All @@ -209,10 +236,12 @@ export async function installKibanaAssetsAndReferencesMultispace({
installedPkg,
spaceId,
assetTags,
esClient,
sloClient,
installAsAdditionalSpace,
});

for (const additionnalSpaceId of Object.keys(
for (const additionalSpaceId of Object.keys(
installedPkg.attributes.additional_spaces_installed_kibana ?? {}
)) {
await installKibanaAssetsAndReferences({
Expand All @@ -222,8 +251,10 @@ export async function installKibanaAssetsAndReferencesMultispace({
pkgTitle,
packageInstallContext,
installedPkg,
spaceId: additionnalSpaceId,
assetTags,
esClient,
sloClient,
spaceId: additionalSpaceId,
installAsAdditionalSpace: true,
});
}
Expand All @@ -239,11 +270,53 @@ export async function installKibanaAssetsAndReferencesMultispace({
installedPkg,
spaceId,
assetTags,
esClient,
sloClient,
installAsAdditionalSpace,
});
}

export async function installSLOAssets({
sloClient,
soClient,
esClient,
spaceId,
sloAssets,
}: {
sloAssets: ArchiveAsset[];
sloClient?: SLOClient;
soClient: SavedObjectsClientContract;
esClient: ElasticsearchClient;
spaceId: string;
}) {
if (!sloClient || !sloAssets.length) {
return [];
}

const installedSLOs = [];
try {
for (const asset of sloAssets) {
const attr = asset.attributes as CreateSLOParams;
const { sloSavedObjectId } = await sloClient.createSLO({
soClient,
esClient,
params: { ...attr, id: asset.id },
spaceId,
});

installedSLOs.push({ id: sloSavedObjectId, type: 'slo', meta: {} });
}
} catch (err) {
// If we fail to install an SLO, we should not fail the whole package install
// but we should log the error
appContextService.getLogger().error(err);
}

return installedSLOs;
}

export async function installKibanaAssetsAndReferences({
esClient,
savedObjectsClient,
logger,
pkgName,
Expand All @@ -253,6 +326,7 @@ export async function installKibanaAssetsAndReferences({
spaceId,
assetTags,
installAsAdditionalSpace,
sloClient,
}: {
savedObjectsClient: SavedObjectsClientContract;
logger: Logger;
Expand All @@ -263,6 +337,8 @@ export async function installKibanaAssetsAndReferences({
spaceId: string;
assetTags?: PackageSpecTags[];
installAsAdditionalSpace?: boolean;
esClient: ElasticsearchClient;
sloClient?: SLOClient;
}) {
const { savedObjectsImporter, savedObjectTagAssignmentService, savedObjectTagClient } =
getSpaceAwareSaveobjectsClients(spaceId);
Expand All @@ -282,11 +358,14 @@ export async function installKibanaAssetsAndReferences({
}

const importedAssets = await installKibanaAssets({
savedObjectsClient,
soClient: savedObjectsClient,
logger,
savedObjectsImporter,
pkgName,
kibanaAssets,
sloClient,
esClient,
spaceId,
});
if (installAsAdditionalSpace) {
const assets = importedAssets.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@ class PackageClientImpl implements PackageClient {
datasets,
spaceId,
installSource: 'custom',
sloClient: appContextService.getSloStart()?.sloClient,
esClient: this.internalEsClient,
savedObjectsClient: this.internalSoClient,
neverIgnoreVerificationError: !force,
Expand Down
Loading