Skip to content
Merged
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 @@ -5,6 +5,7 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
import { SO_SEARCH_LIMIT } from '@kbn/fleet-plugin/common/constants';
import { PREBUILT_RULES_PACKAGE_NAME } from '../../../../../../common/detection_engine/constants';
Expand All @@ -15,11 +16,13 @@ import { GET_ALL_INTEGRATIONS_URL } from '../../../../../../common/api/detection
import { extractIntegrations } from './extract_integrations';
import { sortPackagesBySecurityCategory } from './sort_packages_by_security_category';
import { sortIntegrationsByStatus } from './sort_integrations_by_status';
import { getFleetPackages } from '../../logic/get_fleet_packages';
import { getFleetPackagePolicies } from '../../logic/get_package_policies';

/**
* Returns an array of Fleet integrations and their packages
*/
export const getAllIntegrationsRoute = (router: SecuritySolutionPluginRouter) => {
export const getAllIntegrationsRoute = (router: SecuritySolutionPluginRouter, logger: Logger) => {
router.versioned
.get({
access: 'internal',
Expand All @@ -43,8 +46,8 @@ export const getAllIntegrationsRoute = (router: SecuritySolutionPluginRouter) =>
const fleet = ctx.securitySolution.getInternalFleetServices();

const [packages, packagePolicies] = await Promise.all([
fleet.packages.getPackages(),
fleet.packagePolicy.list(fleet.savedObjects.createInternalScopedSoClient(), {
getFleetPackages(fleet, logger),
getFleetPackagePolicies(fleet, logger, {
perPage: SO_SEARCH_LIMIT,
}),
]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,24 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
import { buildSiemResponse } from '../../../routes/utils';
import type { SecuritySolutionPluginRouter } from '../../../../../types';

import type { GetInstalledIntegrationsResponse } from '../../../../../../common/api/detection_engine/fleet_integrations';
import { GET_INSTALLED_INTEGRATIONS_URL } from '../../../../../../common/api/detection_engine/fleet_integrations';
import { createInstalledIntegrationSet } from './installed_integration_set';
import { getFleetPackages } from '../../logic/get_fleet_packages';
import { getFleetPackagePolicies } from '../../logic/get_package_policies';

/**
* Returns an array of installed Fleet integrations and their packages.
*/
export const getInstalledIntegrationsRoute = (router: SecuritySolutionPluginRouter) => {
export const getInstalledIntegrationsRoute = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
router.versioned
.get({
access: 'internal',
Expand All @@ -42,15 +48,12 @@ export const getInstalledIntegrationsRoute = (router: SecuritySolutionPluginRout

// Pulls all packages into memory just like the main fleet landing page
// No pagination support currently, so cannot batch this call
const allThePackages = await fleet.packages.getPackages();
const allThePackages = await getFleetPackages(fleet, logger);
allThePackages.forEach((fleetPackage) => {
set.addPackage(fleetPackage);
});

const packagePolicies = await fleet.packagePolicy.list(
fleet.savedObjects.createInternalScopedSoClient(),
{}
);
const packagePolicies = await getFleetPackagePolicies(fleet, logger);
packagePolicies.items.forEach((policy) => {
set.addPackagePolicy(policy);
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import type { SecuritySolutionPluginRouter } from '../../../../types';
import { getAllIntegrationsRoute } from './get_all_integrations/route';
import { getInstalledIntegrationsRoute } from './get_installed_integrations/route';

export const registerFleetIntegrationsRoutes = (router: SecuritySolutionPluginRouter) => {
getAllIntegrationsRoute(router);
getInstalledIntegrationsRoute(router);
export const registerFleetIntegrationsRoutes = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
getAllIntegrationsRoute(router, logger);
getInstalledIntegrationsRoute(router, logger);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 { Logger } from '@kbn/core/server';
import type { EndpointInternalFleetServicesInterface } from '../../../../endpoint/services/fleet';

export async function getFleetPackages(
fleet: EndpointInternalFleetServicesInterface,
logger: Logger
) {
try {
logger.debug('getFleetPackages: Fetching Fleet packages');
const packages = await fleet.packages.getPackages();
logger.debug(`getFleetPackages: Fetched Fleet packages: ${packages.length} items`);
return packages;
} catch (error) {
logger.error(`getFleetPackages: Error fetching Fleet packages`, error);
throw error;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* 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 { Logger } from '@kbn/core/server';
import type { ListWithKuery } from '@kbn/fleet-plugin/common';
import type { EndpointInternalFleetServicesInterface } from '../../../../endpoint/services/fleet';

export async function getFleetPackagePolicies(
fleet: EndpointInternalFleetServicesInterface,
logger: Logger,
options: ListWithKuery & { spaceId?: string } = {}
) {
try {
logger.debug('getFleetPackagePolicies: Fetching Fleet package policies');
const soClient = fleet.savedObjects.createInternalScopedSoClient();
const packagePolicies = await fleet.packagePolicy.list(soClient, options);
logger.debug(
`getFleetPackagePolicies: Fetched Fleet package policies: ${packagePolicies.total} items`
);
return packagePolicies;
} catch (error) {
logger.error(`getFleetPackagePolicies: Error fetching Fleet package policies`, error);
throw error;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('bootstrap_prebuilt_rules_route', () => {
({ clients, context } = requestContextMock.createTools());
clients.productFeaturesService = createProductFeaturesServiceMock([]);

bootstrapPrebuiltRulesRoute(server.router);
bootstrapPrebuiltRulesRoute(server.router, clients.logger);
});

it('returns information about installed packages', async () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import { BOOTSTRAP_PREBUILT_RULES_URL } from '../../../../../../common/api/detection_engine/prebuilt_rules';
import type { SecuritySolutionPluginRouter } from '../../../../../types';
import { PREBUILT_RULES_OPERATION_SOCKET_TIMEOUT_MS } from '../../constants';
import { bootstrapPrebuiltRulesHandler } from './bootstrap_prebuilt_rules_handler';
import { throttleRequests } from '../../../../../utils/throttle_requests';

export const bootstrapPrebuiltRulesRoute = (router: SecuritySolutionPluginRouter) => {
export const bootstrapPrebuiltRulesRoute = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
router.versioned
.post({
access: 'internal',
Expand All @@ -32,6 +36,8 @@ export const bootstrapPrebuiltRulesRoute = (router: SecuritySolutionPluginRouter
version: '1',
validate: {},
},
throttleRequests(bootstrapPrebuiltRulesHandler)
throttleRequests((context, request, response) => {
return bootstrapPrebuiltRulesHandler(context, request, response, logger);
})
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,12 @@
* 2.0.
*/

import type { IKibanaResponse, KibanaRequest, KibanaResponseFactory } from '@kbn/core/server';
import type {
Logger,
IKibanaResponse,
KibanaRequest,
KibanaResponseFactory,
} from '@kbn/core/server';
import { ProductFeatureSecurityKey } from '@kbn/security-solution-features/keys';
import { transformError } from '@kbn/securitysolution-es-utils';
import { installSecurityAiPromptsPackage } from '../../logic/integrations/install_ai_prompts';
Expand All @@ -25,7 +30,8 @@ import { createPrebuiltRuleObjectsClient } from '../../logic/rule_objects/prebui
export const bootstrapPrebuiltRulesHandler = async (
context: SecuritySolutionRequestHandlerContext,
_: KibanaRequest,
response: KibanaResponseFactory
response: KibanaResponseFactory,
logger: Logger
): Promise<IKibanaResponse<BootstrapPrebuiltRulesResponse>> => {
const siemResponse = buildSiemResponse(response);

Expand All @@ -47,7 +53,7 @@ export const bootstrapPrebuiltRulesHandler = async (
const packageResults: PackageInstallStatus[] = [];

// Install packages sequentially to avoid high memory usage
const prebuiltRulesResult = await installPrebuiltRulesPackage(securityContext);
const prebuiltRulesResult = await installPrebuiltRulesPackage(securityContext, logger);
packageResults.push({
name: prebuiltRulesResult.package.name,
version: prebuiltRulesResult.package.version,
Expand All @@ -62,17 +68,18 @@ export const bootstrapPrebuiltRulesHandler = async (
ruleAssetsClient,
ruleObjectsClient,
fleetServices: securityContext.getInternalFleetServices(),
logger,
});
} else {
const endpointResult = await installEndpointPackage(securityContext);
const endpointResult = await installEndpointPackage(securityContext, logger);
packageResults.push({
name: endpointResult.package.name,
version: endpointResult.package.version,
status: endpointResult.status,
});
}

const securityAiPromptsResult = await installSecurityAiPromptsPackage(securityContext);
const securityAiPromptsResult = await installSecurityAiPromptsPackage(securityContext, logger);

if (securityAiPromptsResult !== null) {
packageResults.push({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ describe('add_prepackaged_rules_route', () => {
context.core.elasticsearch.client.asCurrentUser.search.mockResolvedValue(
elasticsearchClientMock.createSuccessTransportRequestPromise(getBasicEmptySearchResponse())
);
installPrebuiltRulesAndTimelinesRoute(server.router);
installPrebuiltRulesAndTimelinesRoute(server.router, clients.logger);
});

describe('status codes', () => {
Expand Down Expand Up @@ -238,6 +238,7 @@ describe('add_prepackaged_rules_route', () => {
await legacyCreatePrepackagedRules(
context.securitySolution,
clients.rulesClient,
clients.logger,
mockExceptionsClient
);

Expand All @@ -251,6 +252,7 @@ describe('add_prepackaged_rules_route', () => {
await legacyCreatePrepackagedRules(
context.securitySolution,
clients.rulesClient,
clients.logger,
mockExceptionsClient
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import { transformError } from '@kbn/securitysolution-es-utils';
import { PREBUILT_RULES_URL } from '../../../../../../common/api/detection_engine/prebuilt_rules';
import type { SecuritySolutionPluginRouter } from '../../../../../types';
Expand All @@ -14,7 +15,10 @@ import { PREBUILT_RULES_OPERATION_SOCKET_TIMEOUT_MS } from '../../constants';
// eslint-disable-next-line no-restricted-imports
import { legacyCreatePrepackagedRules } from './legacy_create_prepackaged_rules';

export const installPrebuiltRulesAndTimelinesRoute = (router: SecuritySolutionPluginRouter) => {
export const installPrebuiltRulesAndTimelinesRoute = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
router.versioned
.put({
access: 'public',
Expand Down Expand Up @@ -44,6 +48,7 @@ export const installPrebuiltRulesAndTimelinesRoute = (router: SecuritySolutionPl
const validated = await legacyCreatePrepackagedRules(
await context.securitySolution,
rulesClient,
logger,
undefined
);
return response.ok({ body: validated ?? {} });
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import type { RulesClient } from '@kbn/alerting-plugin/server';
import type { ExceptionListClient } from '@kbn/lists-plugin/server';
import type { InstallPrebuiltRulesAndTimelinesResponse } from '../../../../../../common/api/detection_engine/prebuilt_rules';
Expand Down Expand Up @@ -35,6 +36,7 @@ export class PrepackagedRulesError extends Error {
export const legacyCreatePrepackagedRules = async (
context: SecuritySolutionApiRequestHandlerContext,
rulesClient: RulesClient,
logger: Logger,
exceptionsClient?: ExceptionListClient
): Promise<InstallPrebuiltRulesAndTimelinesResponse> => {
const savedObjectsClient = context.core.savedObjects.client;
Expand All @@ -52,7 +54,11 @@ export const legacyCreatePrepackagedRules = async (
await exceptionsListClient.createEndpointList();
}

const latestPrebuiltRules = await ensureLatestRulesPackageInstalled(ruleAssetsClient, context);
const latestPrebuiltRules = await ensureLatestRulesPackageInstalled(
ruleAssetsClient,
context,
logger
);

const installedPrebuiltRules = rulesToMap(await getExistingPrepackagedRules({ rulesClient }));
const rulesToInstall = getRulesToInstall(latestPrebuiltRules, installedPrebuiltRules);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
*/

import { transformError } from '@kbn/securitysolution-es-utils';
import type { KibanaRequest, KibanaResponseFactory } from '@kbn/core/server';
import type { Logger, KibanaRequest, KibanaResponseFactory } from '@kbn/core/server';
import { SkipRuleInstallReason } from '../../../../../../common/api/detection_engine/prebuilt_rules';
import type {
PerformRuleInstallationResponseBody,
Expand All @@ -27,7 +27,8 @@ import { excludeLicenseRestrictedRules } from '../../logic/utils';
export const performRuleInstallationHandler = async (
context: SecuritySolutionRequestHandlerContext,
request: KibanaRequest<unknown, unknown, PerformRuleInstallationRequestBody>,
response: KibanaResponseFactory
response: KibanaResponseFactory,
logger: Logger
) => {
const siemResponse = buildSiemResponse(response);

Expand All @@ -48,7 +49,7 @@ export const performRuleInstallationHandler = async (

// If this API is used directly without hitting any detection engine
// pages first, the rules package might be missing.
await ensureLatestRulesPackageInstalled(ruleAssetsClient, ctx.securitySolution);
await ensureLatestRulesPackageInstalled(ruleAssetsClient, ctx.securitySolution, logger);

const allLatestVersions = await ruleAssetsClient.fetchLatestVersions();
const currentRuleVersions = await ruleObjectsClient.fetchInstalledRuleVersions();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
* 2.0.
*/

import type { Logger } from '@kbn/core/server';
import {
PERFORM_RULE_INSTALLATION_URL,
PerformRuleInstallationRequestBody,
Expand All @@ -18,7 +19,10 @@ import {
import { routeLimitedConcurrencyTag } from '../../../../../utils/route_limited_concurrency_tag';
import { performRuleInstallationHandler } from './perform_rule_installation_handler';

export const performRuleInstallationRoute = (router: SecuritySolutionPluginRouter) => {
export const performRuleInstallationRoute = (
router: SecuritySolutionPluginRouter,
logger: Logger
) => {
router.versioned
.post({
access: 'internal',
Expand All @@ -44,6 +48,8 @@ export const performRuleInstallationRoute = (router: SecuritySolutionPluginRoute
},
},
},
performRuleInstallationHandler
(context, request, response) => {
return performRuleInstallationHandler(context, request, response, logger);
}
);
};
Loading