From 4bbf16f2eff9849fc355a0034bba80ba298800b7 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 8 Apr 2021 09:19:36 -0500 Subject: [PATCH 01/12] Add preconfiguration API to kibana.yml --- .../resources/base/bin/kibana-docker | 2 ++ x-pack/plugins/fleet/common/types/index.ts | 3 +++ x-pack/plugins/fleet/server/index.ts | 4 ++++ x-pack/plugins/fleet/server/services/setup.ts | 16 ++++++++++++++++ 4 files changed, 25 insertions(+) diff --git a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker index 9617a556e2cdd..b7c347b57a1ef 100755 --- a/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker +++ b/src/dev/build/tasks/os_packages/docker_generator/resources/base/bin/kibana-docker @@ -195,6 +195,8 @@ kibana_vars=( xpack.fleet.agents.elasticsearch.host xpack.fleet.agents.kibana.host xpack.fleet.agents.tlsCheckDisabled + xpack.fleet.agentPolicies + xpack.fleet.packages xpack.fleet.registryUrl xpack.graph.canEditDrillDownUrls xpack.graph.enabled diff --git a/x-pack/plugins/fleet/common/types/index.ts b/x-pack/plugins/fleet/common/types/index.ts index 1984de79a6357..cdea56448f3a2 100644 --- a/x-pack/plugins/fleet/common/types/index.ts +++ b/x-pack/plugins/fleet/common/types/index.ts @@ -7,6 +7,7 @@ export * from './models'; export * from './rest_spec'; +import type { PreconfiguredAgentPolicy, PreconfiguredPackage } from './models/preconfiguration'; export interface FleetConfigType { enabled: boolean; @@ -32,6 +33,8 @@ export interface FleetConfigType { agentPolicyRolloutRateLimitIntervalMs: number; agentPolicyRolloutRateLimitRequestPerInterval: number; }; + agentPolicies?: PreconfiguredAgentPolicy[]; + packages?: PreconfiguredPackage[]; } // Calling Object.entries(PackagesGroupedByStatus) gave `status: string` diff --git a/x-pack/plugins/fleet/server/index.ts b/x-pack/plugins/fleet/server/index.ts index 0178b801f4d2f..c66dd471690eb 100644 --- a/x-pack/plugins/fleet/server/index.ts +++ b/x-pack/plugins/fleet/server/index.ts @@ -15,6 +15,8 @@ import { AGENT_POLLING_REQUEST_TIMEOUT_MS, } from '../common'; +import { PreconfiguredPackagesSchema, PreconfiguredAgentPoliciesSchema } from './types'; + import { FleetPlugin } from './plugin'; export { default as apm } from 'elastic-apm-node'; @@ -77,6 +79,8 @@ export const config: PluginConfigDescriptor = { defaultValue: AGENT_POLICY_ROLLOUT_RATE_LIMIT_REQUEST_PER_INTERVAL, }), }), + packages: schema.maybe(PreconfiguredPackagesSchema), + agentPolicies: schema.maybe(PreconfiguredAgentPoliciesSchema), }), }; diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index b5e2326386e02..5a24f4306b473 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -15,7 +15,9 @@ import type { PackagePolicy } from '../../common'; import { SO_SEARCH_LIMIT } from '../constants'; +import { appContextService } from './app_context'; import { agentPolicyService, addPackageToAgentPolicy } from './agent_policy'; +import { ensurePreconfiguredPackagesAndPolicies } from './preconfiguration'; import { outputService } from './output'; import { ensureInstalledDefaultPackages, @@ -151,6 +153,20 @@ async function createSetupSideEffects( await ensureAgentActionPolicyChangeExists(soClient); + const { agentPolicies: policiesOrUndefined, packages: packagesOrUndefined } = + appContextService.getConfig() ?? {}; + + const policies = policiesOrUndefined ?? []; + const packages = packagesOrUndefined ?? []; + + await ensurePreconfiguredPackagesAndPolicies( + soClient, + esClient, + policies, + packages, + defaultOutput + ); + return { isIntialized: true }; } From f878092013c22f8c2e466f2049a571f8a78fde06 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 8 Apr 2021 10:24:30 -0500 Subject: [PATCH 02/12] Guard against pnst policy recreation after manual delete --- .../plugins/fleet/common/constants/index.ts | 1 + .../common/constants/preconfiguration.ts | 8 ++++ .../plugins/fleet/server/constants/index.ts | 1 + .../fleet/server/services/agent_policy.ts | 37 ++++++++++++++++++- .../fleet/server/services/preconfiguration.ts | 23 ++++++++---- 5 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 x-pack/plugins/fleet/common/constants/preconfiguration.ts diff --git a/x-pack/plugins/fleet/common/constants/index.ts b/x-pack/plugins/fleet/common/constants/index.ts index 5598e63219776..3704533e79b4a 100644 --- a/x-pack/plugins/fleet/common/constants/index.ts +++ b/x-pack/plugins/fleet/common/constants/index.ts @@ -15,6 +15,7 @@ export * from './epm'; export * from './output'; export * from './enrollment_api_key'; export * from './settings'; +export * from './preconfiguration'; // TODO: This is the default `index.max_result_window` ES setting, which dictates // the maximum amount of results allowed to be returned from a search. It's possible diff --git a/x-pack/plugins/fleet/common/constants/preconfiguration.ts b/x-pack/plugins/fleet/common/constants/preconfiguration.ts new file mode 100644 index 0000000000000..4cdd8221d4e98 --- /dev/null +++ b/x-pack/plugins/fleet/common/constants/preconfiguration.ts @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export const PRECONFIGURATION_METADATA_INDEX = '.fleet-preconfiguration'; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 7f5586fb0f034..951112f443816 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -52,4 +52,5 @@ export { // Fleet Server index ENROLLMENT_API_KEYS_INDEX, AGENTS_INDEX, + PRECONFIGURATION_METADATA_INDEX, } from '../../common'; diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index be61a70154b11..a30c3d1cffcfb 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -19,6 +19,7 @@ import { DEFAULT_AGENT_POLICY, AGENT_POLICY_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE, + PRECONFIGURATION_METADATA_INDEX, } from '../constants'; import type { PackagePolicy, @@ -150,7 +151,8 @@ class AgentPolicyService { config: PreconfiguredAgentPolicy ): Promise<{ created: boolean; - policy: AgentPolicy; + policy?: AgentPolicy; + deleted?: string; }> { const { id, ...preconfiguredAgentPolicy } = omit(config, 'package_policies'); const preconfigurationId = String(id); @@ -159,6 +161,29 @@ class AgentPolicyService { search: escapeSearchQueryPhrase(preconfigurationId), }; + // Check to see if a preconfigured policy with te same preconfigurationId was already deleted by the user + try { + const deletionRecord = await esClient.search({ + index: PRECONFIGURATION_METADATA_INDEX, + body: { + query: { + match: { + deleted_preconfiguration_id: preconfigurationId, + }, + }, + }, + }); + + const { total } = deletionRecord.body.hits; + const wasDeleted = (typeof total === 'number' ? total : total.value) > 0; + if (wasDeleted) { + return { created: false, deleted: preconfigurationId }; + } + } catch (e) { + // If ES failed on an index not found error, ignore it. This means nothing has been deleted yet. + if (e.body.status !== 404) throw e; + } + const newAgentPolicyDefaults: Partial = { namespace: 'default', monitoring_enabled: ['logs', 'metrics'], @@ -580,6 +605,16 @@ class AgentPolicyService { } ); } + + if (agentPolicy.preconfiguration_id) { + await esClient.index({ + index: PRECONFIGURATION_METADATA_INDEX, + body: { + deleted_preconfiguration_id: String(agentPolicy.preconfiguration_id), + }, + }); + } + await soClient.delete(SAVED_OBJECT_TYPE, id); await this.triggerAgentPolicyUpdatedEvent(soClient, esClient, 'deleted', id); return { diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 97480fcf6b2a8..0635c64cc179d 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -69,13 +69,13 @@ export async function ensurePreconfiguredPackagesAndPolicies( // Create policies specified in Kibana config const preconfiguredPolicies = await Promise.all( policies.map(async (preconfiguredAgentPolicy) => { - const { created, policy } = await agentPolicyService.ensurePreconfiguredAgentPolicy( + const { created, policy, deleted } = await agentPolicyService.ensurePreconfiguredAgentPolicy( soClient, esClient, omit(preconfiguredAgentPolicy, 'is_managed') // Don't add `is_managed` until the policy has been fully configured ); - if (!created) return { created, policy }; + if (!created) return { created, policy, deleted }; const { package_policies: packagePolicies } = preconfiguredAgentPolicy; const installedPackagePolicies = await Promise.all( @@ -122,22 +122,29 @@ export async function ensurePreconfiguredPackagesAndPolicies( await addPreconfiguredPolicyPackages( soClient, esClient, - policy, + policy!, installedPackagePolicies!, defaultOutput ); // Add the is_managed flag after configuring package policies to avoid errors if (shouldAddIsManagedFlag) { - agentPolicyService.update(soClient, esClient, policy.id, { is_managed: true }); + agentPolicyService.update(soClient, esClient, policy!.id, { is_managed: true }); } } } return { - policies: preconfiguredPolicies.map((p) => ({ - id: p.policy.id, - updated_at: p.policy.updated_at, - })), + policies: preconfiguredPolicies.map((p) => + p.policy + ? { + id: p.policy.id, + updated_at: p.policy.updated_at, + } + : i18n.translate('xpack.fleet.preconfiguration.policyDeleted', { + defaultMessage: 'Preconfigured policy {id} was deleted; skipping creation', + values: { id: p.deleted }, + }) + ), packages: preconfiguredPackages.map((pkg) => pkgToPkgKey(pkg)), }; } From c30ea80300919d43478f966c666176e7e4c86325 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Thu, 8 Apr 2021 15:31:05 -0500 Subject: [PATCH 03/12] Fix type and jest --- .../server/services/preconfiguration.test.ts | 39 +++++++++++++++---- .../fleet/server/services/preconfiguration.ts | 11 ++++-- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index 8a885f9c5c821..850ae8f39fa0b 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -24,6 +24,19 @@ const mockDefaultOutput: Output = { hosts: ['http://127.0.0.1:9201'], }; +const createMockESClient = () => { + const esClient = elasticsearchServiceMock.createInternalClient(); + esClient.search.mockResolvedValue({ + body: { + hits: { + // @ts-ignore + total: 0, + }, + }, + }); + return esClient; +}; + function getPutPreconfiguredPackagesMock() { const soClient = savedObjectsClientMock.create(); soClient.find.mockImplementation(async ({ type, search }) => { @@ -126,7 +139,7 @@ describe('policy preconfiguration', () => { it('should perform a no-op when passed no policies or packages', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + const esClient = createMockESClient(); const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, @@ -142,7 +155,7 @@ describe('policy preconfiguration', () => { it('should install packages successfully', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + const esClient = createMockESClient(); const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, @@ -158,8 +171,14 @@ describe('policy preconfiguration', () => { it('should install packages and configure agent policies successfully', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; - + const esClient = elasticsearchServiceMock.createInternalClient(); + esClient.search.mockResolvedValue({ + body: { + hits: { + total: 0, + }, + }, + }); const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, esClient, @@ -187,7 +206,7 @@ describe('policy preconfiguration', () => { it('should throw an error when trying to install duplicate packages', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; + const esClient = createMockESClient(); await expect( ensurePreconfiguredPackagesAndPolicies( @@ -207,8 +226,14 @@ describe('policy preconfiguration', () => { it('should not attempt to recreate or modify an agent policy if its ID is unchanged', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; - + const esClient = elasticsearchServiceMock.createInternalClient(); + esClient.search.mockResolvedValue({ + body: { + hits: { + total: 0, + }, + }, + }); const { policies: policiesA } = await ensurePreconfiguredPackagesAndPolicies( soClient, esClient, diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 0635c64cc179d..3f8d00b4b9e76 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -140,10 +140,13 @@ export async function ensurePreconfiguredPackagesAndPolicies( id: p.policy.id, updated_at: p.policy.updated_at, } - : i18n.translate('xpack.fleet.preconfiguration.policyDeleted', { - defaultMessage: 'Preconfigured policy {id} was deleted; skipping creation', - values: { id: p.deleted }, - }) + : { + id: p.deleted, + updated_at: i18n.translate('xpack.fleet.preconfiguration.policyDeleted', { + defaultMessage: 'Preconfigured policy {id} was deleted; skipping creation', + values: { id: p.deleted }, + }), + } ), packages: preconfiguredPackages.map((pkg) => pkgToPkgKey(pkg)), }; From bf2dfda154591ed13cb3f82336a4ed5635fadc8c Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Mon, 12 Apr 2021 13:25:57 -0500 Subject: [PATCH 04/12] Fix installing out of date integrations --- .../fleet/server/services/agent_policy.ts | 1 + .../fleet/server/services/package_policy.ts | 38 ++++++++++++------- .../fleet/server/services/preconfiguration.ts | 29 +++++++------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index a30c3d1cffcfb..393f95c139205 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -852,5 +852,6 @@ export async function addPackageToAgentPolicy( await packagePolicyService.create(soClient, esClient, newPackagePolicy, { bumpRevision: false, + skipEnsureInstalled: true, }); } diff --git a/x-pack/plugins/fleet/server/services/package_policy.ts b/x-pack/plugins/fleet/server/services/package_policy.ts index 210c9128b1ec7..d38337a884a0d 100644 --- a/x-pack/plugins/fleet/server/services/package_policy.ts +++ b/x-pack/plugins/fleet/server/services/package_policy.ts @@ -60,7 +60,12 @@ class PackagePolicyService { soClient: SavedObjectsClientContract, esClient: ElasticsearchClient, packagePolicy: NewPackagePolicy, - options?: { id?: string; user?: AuthenticatedUser; bumpRevision?: boolean } + options?: { + id?: string; + user?: AuthenticatedUser; + bumpRevision?: boolean; + skipEnsureInstalled?: boolean; + } ): Promise { // Check that its agent policy does not have a package policy with the same name const parentAgentPolicy = await agentPolicyService.get(soClient, packagePolicy.policy_id); @@ -88,18 +93,25 @@ class PackagePolicyService { // Make sure the associated package is installed if (packagePolicy.package?.name) { - const [, pkgInfo] = await Promise.all([ - ensureInstalledPackage({ - savedObjectsClient: soClient, - pkgName: packagePolicy.package.name, - esClient, - }), - getPackageInfo({ - savedObjectsClient: soClient, - pkgName: packagePolicy.package.name, - pkgVersion: packagePolicy.package.version, - }), - ]); + const pkgInfoPromise = getPackageInfo({ + savedObjectsClient: soClient, + pkgName: packagePolicy.package.name, + pkgVersion: packagePolicy.package.version, + }); + + let pkgInfo; + if (options?.skipEnsureInstalled) pkgInfo = await pkgInfoPromise; + else { + const [, packageInfo] = await Promise.all([ + ensureInstalledPackage({ + savedObjectsClient: soClient, + pkgName: packagePolicy.package.name, + esClient, + }), + pkgInfoPromise, + ]); + pkgInfo = packageInfo; + } // Check if it is a limited package, and if so, check that the corresponding agent policy does not // already contain a package policy for this package diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 3f8d00b4b9e76..4ceebc32d5108 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -19,11 +19,13 @@ import type { PreconfiguredAgentPolicy, PreconfiguredPackage, } from '../../common'; +import { PRECONFIGURATION_METADATA_INDEX } from '../constants'; import { pkgToPkgKey } from './epm/registry'; import { getInstallation } from './epm/packages'; import { ensureInstalledPackage } from './epm/packages/install'; import { agentPolicyService, addPackageToAgentPolicy } from './agent_policy'; +import { packagePolicyService } from './package_policy'; export type InputsOverride = Partial & { vars?: Array; @@ -165,20 +167,19 @@ async function addPreconfiguredPolicyPackages( >, defaultOutput: Output ) { - return await Promise.all( - installedPackagePolicies.map(async ({ installedPackage, name, description, inputs }) => - addPackageToAgentPolicy( - soClient, - esClient, - installedPackage, - agentPolicy, - defaultOutput, - name, - description, - (policy) => overridePackageInputs(policy, inputs) - ) - ) - ); + // Add packages synchronously to avoid overwriting + for (const { installedPackage, name, description, inputs } of installedPackagePolicies) { + await addPackageToAgentPolicy( + soClient, + esClient, + installedPackage, + agentPolicy, + defaultOutput, + name, + description, + (policy) => overridePackageInputs(policy, inputs) + ); + } } async function ensureInstalledPreconfiguredPackage( From f1dbd6679fc17a39d4fb85fda54ff103ad8cf507 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Mon, 12 Apr 2021 16:08:20 -0500 Subject: [PATCH 05/12] Fix typecheck --- .../server/services/preconfiguration.test.ts | 20 ++++--------------- .../fleet/server/services/preconfiguration.ts | 2 -- 2 files changed, 4 insertions(+), 18 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index 850ae8f39fa0b..78b8234ec7c41 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -171,14 +171,8 @@ describe('policy preconfiguration', () => { it('should install packages and configure agent policies successfully', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createInternalClient(); - esClient.search.mockResolvedValue({ - body: { - hits: { - total: 0, - }, - }, - }); + const esClient = createMockESClient(); + const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, esClient, @@ -226,14 +220,8 @@ describe('policy preconfiguration', () => { it('should not attempt to recreate or modify an agent policy if its ID is unchanged', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = elasticsearchServiceMock.createInternalClient(); - esClient.search.mockResolvedValue({ - body: { - hits: { - total: 0, - }, - }, - }); + const esClient = createMockESClient(); + const { policies: policiesA } = await ensurePreconfiguredPackagesAndPolicies( soClient, esClient, diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 4ceebc32d5108..75206423ef990 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -19,13 +19,11 @@ import type { PreconfiguredAgentPolicy, PreconfiguredPackage, } from '../../common'; -import { PRECONFIGURATION_METADATA_INDEX } from '../constants'; import { pkgToPkgKey } from './epm/registry'; import { getInstallation } from './epm/packages'; import { ensureInstalledPackage } from './epm/packages/install'; import { agentPolicyService, addPackageToAgentPolicy } from './agent_policy'; -import { packagePolicyService } from './package_policy'; export type InputsOverride = Partial & { vars?: Array; From 53a4ba81a607a92eb46b4a119ad317beb233484c Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Mon, 12 Apr 2021 16:26:01 -0500 Subject: [PATCH 06/12] Move preconfiguration deletion check outside of agent_policy --- .../fleet/server/services/agent_policy.ts | 24 ---------------- .../fleet/server/services/preconfiguration.ts | 28 +++++++++++++++++-- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index 393f95c139205..21682f583d782 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -152,7 +152,6 @@ class AgentPolicyService { ): Promise<{ created: boolean; policy?: AgentPolicy; - deleted?: string; }> { const { id, ...preconfiguredAgentPolicy } = omit(config, 'package_policies'); const preconfigurationId = String(id); @@ -161,29 +160,6 @@ class AgentPolicyService { search: escapeSearchQueryPhrase(preconfigurationId), }; - // Check to see if a preconfigured policy with te same preconfigurationId was already deleted by the user - try { - const deletionRecord = await esClient.search({ - index: PRECONFIGURATION_METADATA_INDEX, - body: { - query: { - match: { - deleted_preconfiguration_id: preconfigurationId, - }, - }, - }, - }); - - const { total } = deletionRecord.body.hits; - const wasDeleted = (typeof total === 'number' ? total : total.value) > 0; - if (wasDeleted) { - return { created: false, deleted: preconfigurationId }; - } - } catch (e) { - // If ES failed on an index not found error, ignore it. This means nothing has been deleted yet. - if (e.body.status !== 404) throw e; - } - const newAgentPolicyDefaults: Partial = { namespace: 'default', monitoring_enabled: ['logs', 'metrics'], diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index 75206423ef990..e49c83f719918 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -19,6 +19,7 @@ import type { PreconfiguredAgentPolicy, PreconfiguredPackage, } from '../../common'; +import { PRECONFIGURATION_METADATA_INDEX } from '../constants'; import { pkgToPkgKey } from './epm/registry'; import { getInstallation } from './epm/packages'; @@ -69,13 +70,36 @@ export async function ensurePreconfiguredPackagesAndPolicies( // Create policies specified in Kibana config const preconfiguredPolicies = await Promise.all( policies.map(async (preconfiguredAgentPolicy) => { - const { created, policy, deleted } = await agentPolicyService.ensurePreconfiguredAgentPolicy( + // Check to see if a preconfigured policy with te same preconfigurationId was already deleted by the user + try { + const preconfigurationId = String(preconfiguredAgentPolicy.preconfiguration_id); + const deletionRecord = await esClient.search({ + index: PRECONFIGURATION_METADATA_INDEX, + body: { + query: { + match: { + deleted_preconfiguration_id: preconfigurationId, + }, + }, + }, + }); + + const { total } = deletionRecord.body.hits; + const wasDeleted = (typeof total === 'number' ? total : total.value) > 0; + if (wasDeleted) { + return { created: false, deleted: preconfigurationId }; + } + } catch (e) { + // If ES failed on an index not found error, ignore it. This means nothing has been deleted yet. + if (e.body.status !== 404) throw e; + } + const { created, policy } = await agentPolicyService.ensurePreconfiguredAgentPolicy( soClient, esClient, omit(preconfiguredAgentPolicy, 'is_managed') // Don't add `is_managed` until the policy has been fully configured ); - if (!created) return { created, policy, deleted }; + if (!created) return { created, policy }; const { package_policies: packagePolicies } = preconfiguredAgentPolicy; const installedPackagePolicies = await Promise.all( From 039cfc5e32a71f72ddbba30bec6d78067b608320 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 12:00:07 -0500 Subject: [PATCH 07/12] Switch deletion records to use savedobjects instead of es --- .../common/constants/preconfiguration.ts | 3 +- .../plugins/fleet/server/constants/index.ts | 2 +- x-pack/plugins/fleet/server/plugin.ts | 2 + .../fleet/server/saved_objects/index.ts | 14 +++++++ .../fleet/server/services/agent_policy.ts | 9 ++--- .../server/services/preconfiguration.test.ts | 23 +++-------- .../fleet/server/services/preconfiguration.ts | 40 ++++++++----------- 7 files changed, 44 insertions(+), 49 deletions(-) diff --git a/x-pack/plugins/fleet/common/constants/preconfiguration.ts b/x-pack/plugins/fleet/common/constants/preconfiguration.ts index 4cdd8221d4e98..376ba551b1359 100644 --- a/x-pack/plugins/fleet/common/constants/preconfiguration.ts +++ b/x-pack/plugins/fleet/common/constants/preconfiguration.ts @@ -5,4 +5,5 @@ * 2.0. */ -export const PRECONFIGURATION_METADATA_INDEX = '.fleet-preconfiguration'; +export const PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE = + 'fleet-preconfiguration-deletion-record'; diff --git a/x-pack/plugins/fleet/server/constants/index.ts b/x-pack/plugins/fleet/server/constants/index.ts index 951112f443816..27af46d0a757d 100644 --- a/x-pack/plugins/fleet/server/constants/index.ts +++ b/x-pack/plugins/fleet/server/constants/index.ts @@ -52,5 +52,5 @@ export { // Fleet Server index ENROLLMENT_API_KEYS_INDEX, AGENTS_INDEX, - PRECONFIGURATION_METADATA_INDEX, + PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, } from '../../common'; diff --git a/x-pack/plugins/fleet/server/plugin.ts b/x-pack/plugins/fleet/server/plugin.ts index 20cfae6bc1cf2..d25b1e13904db 100644 --- a/x-pack/plugins/fleet/server/plugin.ts +++ b/x-pack/plugins/fleet/server/plugin.ts @@ -48,6 +48,7 @@ import { AGENT_SAVED_OBJECT_TYPE, AGENT_EVENT_SAVED_OBJECT_TYPE, ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, + PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, } from './constants'; import { registerSavedObjects, registerEncryptedSavedObjects } from './saved_objects'; import { @@ -133,6 +134,7 @@ const allSavedObjectTypes = [ AGENT_SAVED_OBJECT_TYPE, AGENT_EVENT_SAVED_OBJECT_TYPE, ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, + PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, ]; /** diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 8554c0702f733..58ec3972ca517 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -19,6 +19,7 @@ import { AGENT_ACTION_SAVED_OBJECT_TYPE, ENROLLMENT_API_KEYS_SAVED_OBJECT_TYPE, GLOBAL_SETTINGS_SAVED_OBJECT_TYPE, + PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, } from '../constants'; import { @@ -358,6 +359,19 @@ const getSavedObjectTypes = ( }, }, }, + [PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE]: { + name: PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, + hidden: false, + namespaceType: 'agnostic', + management: { + importableAndExportable: false, + }, + mappings: { + properties: { + preconfiguration_id: { type: 'keyword' }, + }, + }, + }, }); export function registerSavedObjects( diff --git a/x-pack/plugins/fleet/server/services/agent_policy.ts b/x-pack/plugins/fleet/server/services/agent_policy.ts index ce71d8a3a5945..59214e287c873 100644 --- a/x-pack/plugins/fleet/server/services/agent_policy.ts +++ b/x-pack/plugins/fleet/server/services/agent_policy.ts @@ -19,7 +19,7 @@ import { DEFAULT_AGENT_POLICY, AGENT_POLICY_SAVED_OBJECT_TYPE, AGENT_SAVED_OBJECT_TYPE, - PRECONFIGURATION_METADATA_INDEX, + PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, } from '../constants'; import type { PackagePolicy, @@ -585,11 +585,8 @@ class AgentPolicyService { } if (agentPolicy.preconfiguration_id) { - await esClient.index({ - index: PRECONFIGURATION_METADATA_INDEX, - body: { - deleted_preconfiguration_id: String(agentPolicy.preconfiguration_id), - }, + await soClient.create(PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, { + preconfiguration_id: String(agentPolicy.preconfiguration_id), }); } diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index 78b8234ec7c41..8a885f9c5c821 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -24,19 +24,6 @@ const mockDefaultOutput: Output = { hosts: ['http://127.0.0.1:9201'], }; -const createMockESClient = () => { - const esClient = elasticsearchServiceMock.createInternalClient(); - esClient.search.mockResolvedValue({ - body: { - hits: { - // @ts-ignore - total: 0, - }, - }, - }); - return esClient; -}; - function getPutPreconfiguredPackagesMock() { const soClient = savedObjectsClientMock.create(); soClient.find.mockImplementation(async ({ type, search }) => { @@ -139,7 +126,7 @@ describe('policy preconfiguration', () => { it('should perform a no-op when passed no policies or packages', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = createMockESClient(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, @@ -155,7 +142,7 @@ describe('policy preconfiguration', () => { it('should install packages successfully', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = createMockESClient(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, @@ -171,7 +158,7 @@ describe('policy preconfiguration', () => { it('should install packages and configure agent policies successfully', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = createMockESClient(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const { policies, packages } = await ensurePreconfiguredPackagesAndPolicies( soClient, @@ -200,7 +187,7 @@ describe('policy preconfiguration', () => { it('should throw an error when trying to install duplicate packages', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = createMockESClient(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; await expect( ensurePreconfiguredPackagesAndPolicies( @@ -220,7 +207,7 @@ describe('policy preconfiguration', () => { it('should not attempt to recreate or modify an agent policy if its ID is unchanged', async () => { const soClient = getPutPreconfiguredPackagesMock(); - const esClient = createMockESClient(); + const esClient = elasticsearchServiceMock.createClusterClient().asInternalUser; const { policies: policiesA } = await ensurePreconfiguredPackagesAndPolicies( soClient, diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.ts b/x-pack/plugins/fleet/server/services/preconfiguration.ts index e49c83f719918..3bd3169673b31 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.ts @@ -19,7 +19,9 @@ import type { PreconfiguredAgentPolicy, PreconfiguredPackage, } from '../../common'; -import { PRECONFIGURATION_METADATA_INDEX } from '../constants'; +import { PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE } from '../constants'; + +import { escapeSearchQueryPhrase } from './saved_object'; import { pkgToPkgKey } from './epm/registry'; import { getInstallation } from './epm/packages'; @@ -70,29 +72,21 @@ export async function ensurePreconfiguredPackagesAndPolicies( // Create policies specified in Kibana config const preconfiguredPolicies = await Promise.all( policies.map(async (preconfiguredAgentPolicy) => { - // Check to see if a preconfigured policy with te same preconfigurationId was already deleted by the user - try { - const preconfigurationId = String(preconfiguredAgentPolicy.preconfiguration_id); - const deletionRecord = await esClient.search({ - index: PRECONFIGURATION_METADATA_INDEX, - body: { - query: { - match: { - deleted_preconfiguration_id: preconfigurationId, - }, - }, - }, - }); - - const { total } = deletionRecord.body.hits; - const wasDeleted = (typeof total === 'number' ? total : total.value) > 0; - if (wasDeleted) { - return { created: false, deleted: preconfigurationId }; - } - } catch (e) { - // If ES failed on an index not found error, ignore it. This means nothing has been deleted yet. - if (e.body.status !== 404) throw e; + // Check to see if a preconfigured policy with the same preconfigurationId was already deleted by the user + const preconfigurationId = String(preconfiguredAgentPolicy.id); + const searchParams = { + searchFields: ['preconfiguration_id'], + search: escapeSearchQueryPhrase(preconfigurationId), + }; + const deletionRecords = await soClient.find({ + type: PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE, + ...searchParams, + }); + const wasDeleted = deletionRecords.total > 0; + if (wasDeleted) { + return { created: false, deleted: preconfigurationId }; } + const { created, policy } = await agentPolicyService.ensurePreconfiguredAgentPolicy( soClient, esClient, From 50b682ba2c069f69cd2a9f1d2797aa44d238a59d Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 12:25:19 -0500 Subject: [PATCH 08/12] Ensure default policies after preconfig --- x-pack/plugins/fleet/server/services/setup.ts | 51 ++++++++++--------- 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index 5a24f4306b473..e38d4187992da 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -50,17 +50,10 @@ async function createSetupSideEffects( soClient: SavedObjectsClientContract, esClient: ElasticsearchClient ): Promise { - const [ - installedPackages, - defaultOutput, - { created: defaultAgentPolicyCreated, policy: defaultAgentPolicy }, - { created: defaultFleetServerPolicyCreated, policy: defaultFleetServerPolicy }, - ] = await Promise.all([ + const [installedPackages, defaultOutput] = await Promise.all([ // packages installed by default ensureInstalledDefaultPackages(soClient, esClient), outputService.ensureDefaultOutput(soClient), - agentPolicyService.ensureDefaultAgentPolicy(soClient, esClient), - agentPolicyService.ensureDefaultFleetServerAgentPolicy(soClient, esClient), updateFleetRoleIfExists(esClient), settingsService.getSettings(soClient).catch((e: any) => { if (e.isBoom && e.output.statusCode === 404) { @@ -88,6 +81,32 @@ async function createSetupSideEffects( esClient, }); + const { agentPolicies: policiesOrUndefined, packages: packagesOrUndefined } = + appContextService.getConfig() ?? {}; + + const policies = policiesOrUndefined ?? []; + const packages = packagesOrUndefined ?? []; + + await ensurePreconfiguredPackagesAndPolicies( + soClient, + esClient, + policies, + packages, + defaultOutput + ); + + // Ensure the predefined default policies AFTER loading preconfigured policies. This allows the kibana config + // to override the default agent policies. + + const [ + { created: defaultAgentPolicyCreated, policy: defaultAgentPolicy }, + { created: defaultFleetServerPolicyCreated, policy: defaultFleetServerPolicy }, + ] = await Promise.all([ + agentPolicyService.ensureDefaultAgentPolicy(soClient, esClient), + agentPolicyService.ensureDefaultFleetServerAgentPolicy(soClient, esClient), + ]); + + // If we just created the default fleet server policy add the fleet server package if (defaultFleetServerPolicyCreated) { await addPackageToAgentPolicy( soClient, @@ -98,8 +117,6 @@ async function createSetupSideEffects( ); } - // If we just created the default fleet server policy add the fleet server package - // If we just created the default policy, ensure default packages are added to it if (defaultAgentPolicyCreated) { const agentPolicyWithPackagePolicies = await agentPolicyService.get( @@ -153,20 +170,6 @@ async function createSetupSideEffects( await ensureAgentActionPolicyChangeExists(soClient); - const { agentPolicies: policiesOrUndefined, packages: packagesOrUndefined } = - appContextService.getConfig() ?? {}; - - const policies = policiesOrUndefined ?? []; - const packages = packagesOrUndefined ?? []; - - await ensurePreconfiguredPackagesAndPolicies( - soClient, - esClient, - policies, - packages, - defaultOutput - ); - return { isIntialized: true }; } From bea7b3ab4d6a15caf56232fbc0b49204d28c6935 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 14:48:53 -0500 Subject: [PATCH 09/12] Fix jest --- .../server/services/preconfiguration.test.ts | 49 ++++++++++--------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts index 8a885f9c5c821..94865f5d3d917 100644 --- a/x-pack/plugins/fleet/server/services/preconfiguration.test.ts +++ b/x-pack/plugins/fleet/server/services/preconfiguration.test.ts @@ -10,6 +10,8 @@ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/serve import type { PreconfiguredAgentPolicy } from '../../common/types'; import type { AgentPolicy, NewPackagePolicy, Output } from '../types'; +import { AGENT_POLICY_SAVED_OBJECT_TYPE } from '../constants'; + import { ensurePreconfiguredPackagesAndPolicies } from './preconfiguration'; const mockInstalledPackages = new Map(); @@ -27,30 +29,31 @@ const mockDefaultOutput: Output = { function getPutPreconfiguredPackagesMock() { const soClient = savedObjectsClientMock.create(); soClient.find.mockImplementation(async ({ type, search }) => { - const attributes = mockConfiguredPolicies.get(search!.replace(/"/g, '')); - if (attributes) { - return { - saved_objects: [ - { - id: `mocked-${attributes.preconfiguration_id}`, - attributes, - type: type as string, - score: 1, - references: [], - }, - ], - total: 1, - page: 1, - per_page: 1, - }; - } else { - return { - saved_objects: [], - total: 0, - page: 1, - per_page: 0, - }; + if (type === AGENT_POLICY_SAVED_OBJECT_TYPE) { + const attributes = mockConfiguredPolicies.get(search!.replace(/"/g, '')); + if (attributes) { + return { + saved_objects: [ + { + id: `mocked-${attributes.preconfiguration_id}`, + attributes, + type: type as string, + score: 1, + references: [], + }, + ], + total: 1, + page: 1, + per_page: 1, + }; + } } + return { + saved_objects: [], + total: 0, + page: 1, + per_page: 0, + }; }); soClient.create.mockImplementation(async (type, policy) => { const attributes = policy as AgentPolicy; From 71e39555f9779ba747f3023d94e396cdd1f7caac Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 15:16:27 -0500 Subject: [PATCH 10/12] Handle preconfiguration errors with toasts --- .../common/types/rest_spec/ingest_setup.ts | 1 + .../fleet/public/applications/fleet/app.tsx | 11 ++++++++- .../fleet/server/routes/setup/handlers.ts | 7 +++--- x-pack/plugins/fleet/server/services/setup.ts | 24 ++++++++++++------- 4 files changed, 29 insertions(+), 14 deletions(-) diff --git a/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts b/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts index 12054aff124f7..21153f86750ff 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts @@ -7,4 +7,5 @@ export interface PostIngestSetupResponse { isInitialized: boolean; + preconfigurationError: { name: string; message: string } | undefined; } diff --git a/x-pack/plugins/fleet/public/applications/fleet/app.tsx b/x-pack/plugins/fleet/public/applications/fleet/app.tsx index 2c24468b14782..5663bd4768d5c 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/app.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/app.tsx @@ -28,6 +28,7 @@ import { sendSetup, useBreadcrumbs, useConfig, + useStartServices, } from './hooks'; import { Error, Loading } from './components'; import { IntraAppStateProvider } from './hooks/use_intra_app_state'; @@ -59,6 +60,7 @@ const Panel = styled(EuiPanel)` export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { useBreadcrumbs('base'); + const { notifications } = useStartServices(); const [isPermissionsLoading, setIsPermissionsLoading] = useState(false); const [permissionsError, setPermissionsError] = useState(); @@ -81,6 +83,13 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { if (setupResponse.error) { setInitializationError(setupResponse.error); } + if (setupResponse.data.preconfigurationError) { + notifications.toasts.addError(setupResponse.data.preconfigurationError, { + title: i18n.translate('xpack.fleet.setup.uiPreconfigurationErrorTitle', { + defaultMessage: 'Configuration error', + }), + }); + } } catch (err) { setInitializationError(err); } @@ -92,7 +101,7 @@ export const WithPermissionsAndSetup: React.FC = memo(({ children }) => { setPermissionsError('REQUEST_ERROR'); } })(); - }, []); + }, [notifications.toasts]); if (isPermissionsLoading || permissionsError) { return ( diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.ts index a7fdcf78f4be9..e94c9470dd350 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.ts @@ -63,13 +63,13 @@ export const createFleetSetupHandler: RequestHandler< try { const soClient = context.core.savedObjects.client; const esClient = context.core.elasticsearch.client.asCurrentUser; - await setupIngestManager(soClient, esClient); + const body = await setupIngestManager(soClient, esClient); await setupFleet(soClient, esClient, { forceRecreate: request.body?.forceRecreate ?? false, }); return response.ok({ - body: { isInitialized: true }, + body, }); } catch (error) { return defaultIngestErrorHandler({ error, response }); @@ -81,8 +81,7 @@ export const FleetSetupHandler: RequestHandler = async (context, request, respon const esClient = context.core.elasticsearch.client.asCurrentUser; try { - const body: PostIngestSetupResponse = { isInitialized: true }; - await setupIngestManager(soClient, esClient); + const body: PostIngestSetupResponse = await setupIngestManager(soClient, esClient); return response.ok({ body, }); diff --git a/x-pack/plugins/fleet/server/services/setup.ts b/x-pack/plugins/fleet/server/services/setup.ts index e38d4187992da..6d98bc4263a16 100644 --- a/x-pack/plugins/fleet/server/services/setup.ts +++ b/x-pack/plugins/fleet/server/services/setup.ts @@ -36,7 +36,8 @@ const FLEET_ENROLL_USERNAME = 'fleet_enroll'; const FLEET_ENROLL_ROLE = 'fleet_enroll'; export interface SetupStatus { - isIntialized: true | undefined; + isInitialized: boolean; + preconfigurationError: { name: string; message: string } | undefined; } export async function setupIngestManager( @@ -86,14 +87,19 @@ async function createSetupSideEffects( const policies = policiesOrUndefined ?? []; const packages = packagesOrUndefined ?? []; + let preconfigurationError; - await ensurePreconfiguredPackagesAndPolicies( - soClient, - esClient, - policies, - packages, - defaultOutput - ); + try { + await ensurePreconfiguredPackagesAndPolicies( + soClient, + esClient, + policies, + packages, + defaultOutput + ); + } catch (e) { + preconfigurationError = { name: e.name, message: e.message }; + } // Ensure the predefined default policies AFTER loading preconfigured policies. This allows the kibana config // to override the default agent policies. @@ -170,7 +176,7 @@ async function createSetupSideEffects( await ensureAgentActionPolicyChangeExists(soClient); - return { isIntialized: true }; + return { isInitialized: true, preconfigurationError }; } async function updateFleetRoleIfExists(esClient: ElasticsearchClient) { From f5f18f7900f5b749d4fd7d585e372c2f089fc102 Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 15:41:46 -0500 Subject: [PATCH 11/12] Type fix --- x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts b/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts index 21153f86750ff..2180b66908498 100644 --- a/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts +++ b/x-pack/plugins/fleet/common/types/rest_spec/ingest_setup.ts @@ -7,5 +7,5 @@ export interface PostIngestSetupResponse { isInitialized: boolean; - preconfigurationError: { name: string; message: string } | undefined; + preconfigurationError?: { name: string; message: string }; } From cb65cead807c0774d110fabd5bf667d94890801f Mon Sep 17 00:00:00 2001 From: Zacqary Xeper Date: Tue, 13 Apr 2021 16:02:26 -0500 Subject: [PATCH 12/12] Fix typecheck --- x-pack/plugins/fleet/server/routes/setup/handlers.test.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts index 469b2409f140a..2618f3de0d534 100644 --- a/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/setup/handlers.test.ts @@ -45,7 +45,9 @@ describe('FleetSetupHandler', () => { }); it('POST /setup succeeds w/200 and body of resolved value', async () => { - mockSetupIngestManager.mockImplementation(() => Promise.resolve({ isIntialized: true })); + mockSetupIngestManager.mockImplementation(() => + Promise.resolve({ isInitialized: true, preconfigurationError: undefined }) + ); await FleetSetupHandler(context, request, response); const expectedBody: PostIngestSetupResponse = { isInitialized: true };