From 04dbceced5be9a881575492f6f1f5bf3cd1ab2b5 Mon Sep 17 00:00:00 2001 From: Kibana Machine <42973632+kibanamachine@users.noreply.github.com> Date: Tue, 6 Jul 2021 20:03:40 -0400 Subject: [PATCH] [Osquery] Fix issue with plugin initialization (#100208) (#104562) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Patryk KopyciƄski --- x-pack/plugins/fleet/server/plugin.ts | 16 +------ x-pack/plugins/fleet/server/services/index.ts | 8 ++-- x-pack/plugins/osquery/public/plugin.ts | 40 ++++++++--------- x-pack/plugins/osquery/server/routes/index.ts | 2 + .../routes/status/create_status_route.ts | 35 +++++++++++++++ .../osquery/server/routes/status/index.ts | 14 ++++++ .../endpoint/endpoint_app_context_services.ts | 7 ++- .../server/endpoint/mocks.ts | 2 +- .../endpoint/routes/actions/isolation.test.ts | 34 ++++++++++----- .../endpoint/routes/metadata/metadata.test.ts | 43 +++++++++++-------- .../routes/metadata/metadata_v1.test.ts | 6 +-- 11 files changed, 128 insertions(+), 79 deletions(-) create mode 100644 x-pack/plugins/osquery/server/routes/status/create_status_route.ts create mode 100644 x-pack/plugins/osquery/server/routes/status/index.ts diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 1f8f54261c721..a4c0df6dd3708 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -15,7 +15,6 @@ import type { PluginInitializerContext, SavedObjectsServiceStart, HttpServiceSetup, - SavedObjectsClientContract, RequestHandlerContext, KibanaRequest, } from 'kibana/server'; @@ -30,12 +29,7 @@ import type { } from '../../encrypted_saved_objects/server'; import type { SecurityPluginSetup, SecurityPluginStart } from '../../security/server'; import type { PluginSetupContract as FeaturesPluginSetup } from '../../features/server'; -import type { - EsAssetReference, - FleetConfigType, - NewPackagePolicy, - UpdatePackagePolicy, -} from '../common'; +import type { FleetConfigType, NewPackagePolicy, UpdatePackagePolicy } from '../common'; import { INTEGRATIONS_PLUGIN_ID } from '../common'; import type { CloudSetup } from '../../cloud/server'; @@ -309,13 +303,7 @@ export class FleetPlugin }), esIndexPatternService: new ESIndexPatternSavedObjectService(), packageService: { - getInstalledEsAssetReferences: async ( - savedObjectsClient: SavedObjectsClientContract, - pkgName: string - ): Promise => { - const installation = await getInstallation({ savedObjectsClient, pkgName }); - return installation?.installed_es || []; - }, + getInstallation, }, agentService: { getAgent: getAgentById, diff --git a/x-pack/plugins/fleet/server/services/index.ts b/x-pack/plugins/fleet/server/services/index.ts index f82415987e5ac..f4355320c5a6a 100644 --- a/x-pack/plugins/fleet/server/services/index.ts +++ b/x-pack/plugins/fleet/server/services/index.ts @@ -8,11 +8,12 @@ import type { KibanaRequest } from 'kibana/server'; import type { ElasticsearchClient, SavedObjectsClientContract } from 'kibana/server'; -import type { AgentStatus, Agent, EsAssetReference } from '../types'; +import type { AgentStatus, Agent } from '../types'; import type { getAgentById, getAgentsByKuery } from './agents'; import type { agentPolicyService } from './agent_policy'; import * as settingsService from './settings'; +import type { getInstallation } from './epm/packages'; export { ESIndexPatternSavedObjectService } from './es_index_pattern'; export { getRegistryUrl } from './epm/registry/registry_url'; @@ -33,10 +34,7 @@ export interface ESIndexPatternService { */ export interface PackageService { - getInstalledEsAssetReferences( - savedObjectsClient: SavedObjectsClientContract, - pkgName: string - ): Promise; + getInstallation: typeof getInstallation; } /** diff --git a/x-pack/plugins/osquery/public/plugin.ts b/x-pack/plugins/osquery/public/plugin.ts index abdea2df3b2b5..631f3adba4c47 100644 --- a/x-pack/plugins/osquery/public/plugin.ts +++ b/x-pack/plugins/osquery/public/plugin.ts @@ -21,12 +21,11 @@ import { Storage } from '../../../../src/plugins/kibana_utils/public'; import { OsqueryPluginSetup, OsqueryPluginStart, - // SetupPlugins, StartPlugins, AppPluginStartDependencies, } from './types'; import { OSQUERY_INTEGRATION_NAME, PLUGIN_NAME } from '../common'; -import { epmRouteService, GetPackagesResponse } from '../../fleet/common'; +import { Installation } from '../../fleet/common'; import { LazyOsqueryManagedPolicyCreateImportExtension, LazyOsqueryManagedPolicyEditExtension, @@ -47,12 +46,9 @@ export function toggleOsqueryPlugin( } http - .fetch(epmRouteService.getListPath(), { query: { experimental: true } }) - .then(({ response }) => { - const installed = response.find( - (integration) => - integration?.name === OSQUERY_INTEGRATION_NAME && integration?.status === 'installed' - ); + .fetch(`/internal/osquery/status`) + .then((response) => { + const installed = response?.install_status === 'installed'; if (installed && registerExtension) { registerExtension({ @@ -137,24 +133,26 @@ export class OsqueryPlugin implements Plugin(); + if (!config.enabled) { + return {}; + } + if (plugins.fleet) { const { registerExtension } = plugins.fleet; - if (config.enabled) { - toggleOsqueryPlugin(this.appUpdater$, core.http, registerExtension); + toggleOsqueryPlugin(this.appUpdater$, core.http, registerExtension); - registerExtension({ - package: OSQUERY_INTEGRATION_NAME, - view: 'package-policy-create', - Component: LazyOsqueryManagedPolicyCreateImportExtension, - }); + registerExtension({ + package: OSQUERY_INTEGRATION_NAME, + view: 'package-policy-create', + Component: LazyOsqueryManagedPolicyCreateImportExtension, + }); - registerExtension({ - package: OSQUERY_INTEGRATION_NAME, - view: 'package-policy-edit', - Component: LazyOsqueryManagedPolicyEditExtension, - }); - } + registerExtension({ + package: OSQUERY_INTEGRATION_NAME, + view: 'package-policy-edit', + Component: LazyOsqueryManagedPolicyEditExtension, + }); } else { this.appUpdater$.next(() => ({ status: AppStatus.inaccessible, diff --git a/x-pack/plugins/osquery/server/routes/index.ts b/x-pack/plugins/osquery/server/routes/index.ts index 7eee5b94fd84d..dd11141b2553f 100644 --- a/x-pack/plugins/osquery/server/routes/index.ts +++ b/x-pack/plugins/osquery/server/routes/index.ts @@ -9,12 +9,14 @@ import { IRouter } from '../../../../../src/core/server'; import { initActionRoutes } from './action'; import { OsqueryAppContext } from '../lib/osquery_app_context_services'; import { initSavedQueryRoutes } from './saved_query'; +import { initStatusRoutes } from './status'; import { initPackRoutes } from './pack'; export const defineRoutes = (router: IRouter, context: OsqueryAppContext) => { const config = context.config(); initActionRoutes(router, context); + initStatusRoutes(router, context); if (config.packs) { initPackRoutes(router); diff --git a/x-pack/plugins/osquery/server/routes/status/create_status_route.ts b/x-pack/plugins/osquery/server/routes/status/create_status_route.ts new file mode 100644 index 0000000000000..d7ea49c6152cd --- /dev/null +++ b/x-pack/plugins/osquery/server/routes/status/create_status_route.ts @@ -0,0 +1,35 @@ +/* + * 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 { OSQUERY_INTEGRATION_NAME } from '../../../common'; +import { IRouter } from '../../../../../../src/core/server'; +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; + +export const createStatusRoute = (router: IRouter, osqueryContext: OsqueryAppContext) => { + router.get( + { + path: '/internal/osquery/status', + validate: false, + }, + async (context, request, response) => { + const soClient = context.core.savedObjects.client; + const isSuperUser = osqueryContext.security.authc + .getCurrentUser(request) + ?.roles.includes('superuser'); + + if (!isSuperUser) { + return response.ok({ body: undefined }); + } + + const packageInfo = await osqueryContext.service + .getPackageService() + ?.getInstallation({ savedObjectsClient: soClient, pkgName: OSQUERY_INTEGRATION_NAME }); + + return response.ok({ body: packageInfo }); + } + ); +}; diff --git a/x-pack/plugins/osquery/server/routes/status/index.ts b/x-pack/plugins/osquery/server/routes/status/index.ts new file mode 100644 index 0000000000000..9e85613165b16 --- /dev/null +++ b/x-pack/plugins/osquery/server/routes/status/index.ts @@ -0,0 +1,14 @@ +/* + * 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 { IRouter } from '../../../../../../src/core/server'; +import { createStatusRoute } from './create_status_route'; +import { OsqueryAppContext } from '../../lib/osquery_app_context_services'; + +export const initStatusRoutes = (router: IRouter, context: OsqueryAppContext) => { + createStatusRoute(router, context); +}; diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index 88ac1cb1d16b3..f10a4a078aad3 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -67,10 +67,9 @@ export const createMetadataService = (packageService: PackageService): MetadataS } if (version === MetadataQueryStrategyVersions.VERSION_2 || !version) { - const assets = await packageService.getInstalledEsAssetReferences( - savedObjectsClient, - 'endpoint' - ); + const assets = + (await packageService.getInstallation({ savedObjectsClient, pkgName: 'endpoint' })) + ?.installed_es ?? []; const expectedTransformAssets = assets.filter( (ref) => ref.type === ElasticsearchAssetType.transform && diff --git a/x-pack/plugins/security_solution/server/endpoint/mocks.ts b/x-pack/plugins/security_solution/server/endpoint/mocks.ts index b2439efc63567..b273cbca6c627 100644 --- a/x-pack/plugins/security_solution/server/endpoint/mocks.ts +++ b/x-pack/plugins/security_solution/server/endpoint/mocks.ts @@ -99,7 +99,7 @@ export const createMockEndpointAppContextServiceStartContract = (): jest.Mocked< export const createMockPackageService = (): jest.Mocked => { return { - getInstalledEsAssetReferences: jest.fn(), + getInstallation: jest.fn(), }; }; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts index 1b1490d3af072..48412abd920d7 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/actions/isolation.test.ts @@ -127,17 +127,29 @@ describe('Host Isolation', () => { endpointAppContextService = new EndpointAppContextService(); const mockSavedObjectClient = savedObjectsClientMock.create(); const mockPackageService = createMockPackageService(); - mockPackageService.getInstalledEsAssetReferences.mockReturnValue( - Promise.resolve([ - { - id: 'logs-endpoint.events.security', - type: ElasticsearchAssetType.indexTemplate, - }, - { - id: `${metadataTransformPrefix}-0.16.0-dev.0`, - type: ElasticsearchAssetType.transform, - }, - ]) + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + dupa: true, + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + }) ); licenseEmitter = new Subject(); licenseService = new LicenseService(); diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts index e6d6879ba1845..5250f7c49d6ad 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata.test.ts @@ -38,11 +38,7 @@ import { } from '../../endpoint_app_context_services'; import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; -import { - Agent, - ElasticsearchAssetType, - EsAssetReference, -} from '../../../../../fleet/common/types/models'; +import { Agent, ElasticsearchAssetType } from '../../../../../fleet/common/types/models'; import { createV1SearchResponse, createV2SearchResponse } from './support/test_support'; import { PackageService } from '../../../../../fleet/server/services'; import { @@ -106,9 +102,7 @@ describe('test endpoint route', () => { beforeEach(() => { endpointAppContextService = new EndpointAppContextService(); mockPackageService = createMockPackageService(); - mockPackageService.getInstalledEsAssetReferences.mockReturnValue( - Promise.resolve(([] as unknown) as EsAssetReference[]) - ); + mockPackageService.getInstallation.mockReturnValue(Promise.resolve(undefined)); endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); mockAgentService = startContract.agentService!; @@ -196,17 +190,28 @@ describe('test endpoint route', () => { beforeEach(() => { endpointAppContextService = new EndpointAppContextService(); mockPackageService = createMockPackageService(); - mockPackageService.getInstalledEsAssetReferences.mockReturnValue( - Promise.resolve([ - { - id: 'logs-endpoint.events.security', - type: ElasticsearchAssetType.indexTemplate, - }, - { - id: `${metadataTransformPrefix}-0.16.0-dev.0`, - type: ElasticsearchAssetType.transform, - }, - ]) + mockPackageService.getInstallation.mockReturnValue( + Promise.resolve({ + installed_kibana: [], + package_assets: [], + es_index_patterns: {}, + name: '', + version: '', + install_status: 'installed', + install_version: '', + install_started_at: '', + install_source: 'registry', + installed_es: [ + { + id: 'logs-endpoint.events.security', + type: ElasticsearchAssetType.indexTemplate, + }, + { + id: `${metadataTransformPrefix}-0.16.0-dev.0`, + type: ElasticsearchAssetType.transform, + }, + ], + }) ); endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); mockAgentService = startContract.agentService!; diff --git a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts index 0d56514e7d395..29b2c231cc4a5 100644 --- a/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts +++ b/x-pack/plugins/security_solution/server/endpoint/routes/metadata/metadata_v1.test.ts @@ -43,7 +43,7 @@ import { import { createMockConfig } from '../../../lib/detection_engine/routes/__mocks__'; import { EndpointDocGenerator } from '../../../../common/endpoint/generate_data'; import { parseExperimentalConfigValue } from '../../../../common/experimental_features'; -import { Agent, EsAssetReference } from '../../../../../fleet/common/types/models'; +import { Agent } from '../../../../../fleet/common/types/models'; import { createV1SearchResponse } from './support/test_support'; import { PackageService } from '../../../../../fleet/server/services'; import type { SecuritySolutionPluginRouter } from '../../../types'; @@ -82,9 +82,7 @@ describe('test endpoint route v1', () => { mockResponse = httpServerMock.createResponseFactory(); endpointAppContextService = new EndpointAppContextService(); mockPackageService = createMockPackageService(); - mockPackageService.getInstalledEsAssetReferences.mockReturnValue( - Promise.resolve(([] as unknown) as EsAssetReference[]) - ); + mockPackageService.getInstallation.mockReturnValue(Promise.resolve(undefined)); startContract = createMockEndpointAppContextServiceStartContract(); endpointAppContextService.start({ ...startContract, packageService: mockPackageService }); mockAgentService = startContract.agentService!;