diff --git a/x-pack/plugins/fleet/common/constants/epm.ts b/x-pack/plugins/fleet/common/constants/epm.ts index 734d578687bcd..5137e422e0975 100644 --- a/x-pack/plugins/fleet/common/constants/epm.ts +++ b/x-pack/plugins/fleet/common/constants/epm.ts @@ -32,6 +32,13 @@ export const STANDALONE_RUN_INSTRUCTIONS = './elastic-agent install'; removable, but it doesn't install by default. Following the table, it needs to be in `unremovablePackages` and in `autoUpdatePackages`, but not in `defaultPackages`. + + +We also define "auto upgrade policies" packages below. These are packages that are considered "stack-aligned" +and require policies to be auto-upgraded in order to properly function. Commonly, packages that ship custom policy +editor UI's in the Kibana codebase will be included in this set of packages to avoid backwards-compatibility concerns +in their custom policy editor implementations. + */ export const unremovablePackages = [ @@ -49,6 +56,8 @@ export const autoUpdatePackages = [ FLEET_SYNTHETICS_PACKAGE, ]; +export const autoUpgradePoliciesPackages = [FLEET_APM_PACKAGE, FLEET_SYNTHETICS_PACKAGE]; + export const agentAssetTypes = { Input: 'input', } as const; diff --git a/x-pack/plugins/fleet/common/constants/preconfiguration.ts b/x-pack/plugins/fleet/common/constants/preconfiguration.ts index 2ec67393df76b..3e7377477c93e 100644 --- a/x-pack/plugins/fleet/common/constants/preconfiguration.ts +++ b/x-pack/plugins/fleet/common/constants/preconfiguration.ts @@ -5,6 +5,8 @@ * 2.0. */ +import { uniqBy } from 'lodash'; + import type { PreconfiguredAgentPolicy } from '../types'; import { @@ -13,6 +15,7 @@ import { FLEET_SERVER_PACKAGE, autoUpdatePackages, monitoringTypes, + autoUpgradePoliciesPackages, } from './epm'; export const PRECONFIGURATION_DELETION_RECORD_SAVED_OBJECT_TYPE = @@ -72,6 +75,18 @@ export const AUTO_UPDATE_PACKAGES = autoUpdatePackages.map((name) => ({ version: PRECONFIGURATION_LATEST_KEYWORD, })); +// These packages default to `keep_policies_up_to_date: true` and don't allow users to opt out +export const AUTO_UPGRADE_POLICIES_PACKAGES = autoUpgradePoliciesPackages.map((name) => ({ + name, + version: PRECONFIGURATION_LATEST_KEYWORD, +})); + +// Controls whether the `Keep Policies up to date` setting is exposed to the user +export const KEEP_POLICIES_UP_TO_DATE_PACKAGES = uniqBy( + [...AUTO_UPGRADE_POLICIES_PACKAGES, ...DEFAULT_PACKAGES, ...AUTO_UPDATE_PACKAGES], + ({ name }) => name +); + export interface PreconfigurationError { package?: { name: string; version: string }; agentPolicy?: { name: string }; diff --git a/x-pack/plugins/fleet/common/types/models/epm.ts b/x-pack/plugins/fleet/common/types/models/epm.ts index 078281fec9806..f7b446cc53c7d 100644 --- a/x-pack/plugins/fleet/common/types/models/epm.ts +++ b/x-pack/plugins/fleet/common/types/models/epm.ts @@ -402,7 +402,7 @@ export interface Installation extends SavedObjectAttributes { install_version: string; install_started_at: string; install_source: InstallSource; - keep_policies_up_to_date: boolean; + keep_policies_up_to_date?: boolean; } export interface PackageUsageStats { diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/keep_policies_up_to_date_switch.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/keep_policies_up_to_date_switch.tsx index 751282cc42288..364b24ab48912 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/keep_policies_up_to_date_switch.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/components/keep_policies_up_to_date_switch.tsx @@ -12,11 +12,13 @@ import { EuiSwitch, EuiSpacer, EuiText, EuiFlexGroup, EuiFlexItem, EuiIcon } fro interface Props { checked: boolean; + disabled?: boolean; onChange: () => void; } export const KeepPoliciesUpToDateSwitch: React.FunctionComponent = ({ checked, + disabled = false, onChange, }) => ( <> @@ -27,6 +29,7 @@ export const KeepPoliciesUpToDateSwitch: React.FunctionComponent = ({ )} checked={checked} onChange={onChange} + disabled={disabled} /> @@ -35,10 +38,17 @@ export const KeepPoliciesUpToDateSwitch: React.FunctionComponent = ({ - + {disabled ? ( + + ) : ( + + )} diff --git a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx index 5fa274c0feb98..31a01ffd7bdc8 100644 --- a/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx +++ b/x-pack/plugins/fleet/public/applications/integrations/sections/epm/screens/detail/settings/settings.tsx @@ -9,7 +9,6 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from 'react'; import styled from 'styled-components'; import { FormattedMessage } from '@kbn/i18n/react'; import semverLt from 'semver/functions/lt'; -import { uniq } from 'lodash'; import { EuiCallOut, @@ -35,8 +34,8 @@ import { } from '../../../../../hooks'; import { PACKAGE_POLICY_SAVED_OBJECT_TYPE, - AUTO_UPDATE_PACKAGES, - DEFAULT_PACKAGES, + KEEP_POLICIES_UP_TO_DATE_PACKAGES, + AUTO_UPGRADE_POLICIES_PACKAGES, } from '../../../../../constants'; import { KeepPoliciesUpToDateSwitch } from '../components'; @@ -107,11 +106,11 @@ export const SettingsPage: React.FC = memo(({ packageInfo }: Props) => { const { notifications } = useStartServices(); const shouldShowKeepPoliciesUpToDateSwitch = useMemo(() => { - const packages = [...DEFAULT_PACKAGES, ...AUTO_UPDATE_PACKAGES]; - - const packageNames = uniq(packages.map((pkg) => pkg.name)); + return KEEP_POLICIES_UP_TO_DATE_PACKAGES.some((pkg) => pkg.name === name); + }, [name]); - return packageNames.includes(name); + const isShowKeepPoliciesUpToDateSwitchDisabled = useMemo(() => { + return AUTO_UPGRADE_POLICIES_PACKAGES.some((pkg) => pkg.name === name); }, [name]); const [keepPoliciesUpToDateSwitchValue, setKeepPoliciesUpToDateSwitchValue] = useState( @@ -274,6 +273,7 @@ export const SettingsPage: React.FC = memo(({ packageInfo }: Props) => { diff --git a/x-pack/plugins/fleet/public/constants/index.ts b/x-pack/plugins/fleet/public/constants/index.ts index 38b7875c93b3b..139f9d3d1f1c4 100644 --- a/x-pack/plugins/fleet/public/constants/index.ts +++ b/x-pack/plugins/fleet/public/constants/index.ts @@ -21,6 +21,8 @@ export { // Preconfiguration AUTO_UPDATE_PACKAGES, DEFAULT_PACKAGES, + KEEP_POLICIES_UP_TO_DATE_PACKAGES, + AUTO_UPGRADE_POLICIES_PACKAGES, } from '../../common/constants'; export * from './page_paths'; diff --git a/x-pack/plugins/fleet/server/saved_objects/index.ts b/x-pack/plugins/fleet/server/saved_objects/index.ts index 3b459c938b5f0..26adf7b9fcbc7 100644 --- a/x-pack/plugins/fleet/server/saved_objects/index.ts +++ b/x-pack/plugins/fleet/server/saved_objects/index.ts @@ -35,7 +35,7 @@ import { import { migratePackagePolicyToV7140, migrateInstallationToV7140 } from './migrations/to_v7_14_0'; import { migratePackagePolicyToV7150 } from './migrations/to_v7_15_0'; import { migrateInstallationToV7160, migratePackagePolicyToV7160 } from './migrations/to_v7_16_0'; -import { migrateOutputToV800 } from './migrations/to_v8_0_0'; +import { migrateInstallationToV800, migrateOutputToV800 } from './migrations/to_v8_0_0'; /* * Saved object types and mappings @@ -255,6 +255,7 @@ const getSavedObjectTypes = ( '7.14.0': migrateInstallationToV7140, '7.14.1': migrateInstallationToV7140, '7.16.0': migrateInstallationToV7160, + '8.0.0': migrateInstallationToV800, }, }, [ASSETS_SAVED_OBJECT_TYPE]: { diff --git a/x-pack/plugins/fleet/server/saved_objects/migrations/to_v8_0_0.ts b/x-pack/plugins/fleet/server/saved_objects/migrations/to_v8_0_0.ts index 77797b3d27ba5..61db35fd9faf5 100644 --- a/x-pack/plugins/fleet/server/saved_objects/migrations/to_v8_0_0.ts +++ b/x-pack/plugins/fleet/server/saved_objects/migrations/to_v8_0_0.ts @@ -7,8 +7,8 @@ import type { SavedObjectMigrationFn } from 'kibana/server'; -import type { Output } from '../../../common'; -import {} from '../../../common'; +import type { Installation, Output } from '../../../common'; +import { AUTO_UPGRADE_POLICIES_PACKAGES } from '../../../common'; export const migrateOutputToV800: SavedObjectMigrationFn = ( outputDoc, @@ -20,3 +20,20 @@ export const migrateOutputToV800: SavedObjectMigrationFn = ( return outputDoc; }; + +export const migrateInstallationToV800: SavedObjectMigrationFn = ( + installationDoc, + migrationContext +) => { + const updatedInstallationDoc = installationDoc; + + const shouldKeepPoliciesUpToDate = AUTO_UPGRADE_POLICIES_PACKAGES.some( + (pkg) => pkg.name === updatedInstallationDoc.attributes.name + ); + + if (shouldKeepPoliciesUpToDate) { + updatedInstallationDoc.attributes.keep_policies_up_to_date = true; + } + + return updatedInstallationDoc; +}; diff --git a/x-pack/plugins/fleet/server/services/epm/packages/install.ts b/x-pack/plugins/fleet/server/services/epm/packages/install.ts index 5b86c944feb39..db26dc3a20a80 100644 --- a/x-pack/plugins/fleet/server/services/epm/packages/install.ts +++ b/x-pack/plugins/fleet/server/services/epm/packages/install.ts @@ -18,7 +18,7 @@ import type { InstallablePackage, InstallSource, } from '../../../../common'; -import { DEFAULT_PACKAGES } from '../../../../common'; +import { AUTO_UPGRADE_POLICIES_PACKAGES } from '../../../../common'; import { IngestManagerError, PackageOperationNotSupportedError, @@ -534,11 +534,14 @@ export async function createInstallation(options: { const removable = !isUnremovablePackage(pkgName); const toSaveESIndexPatterns = generateESIndexPatterns(packageInfo.data_streams); - // For default packages, default the `keep_policies_up_to_date` setting to true. For all other - // package, default it to false. - const defaultKeepPoliciesUpToDate = DEFAULT_PACKAGES.some( + // For "stack-aligned" packages, default the `keep_policies_up_to_date` setting to true. For all other + // packages, default it to undefined. Use undefined rather than false to allow us to differentiate + // between "unset" and "user explicitly disabled". + const defaultKeepPoliciesUpToDate = AUTO_UPGRADE_POLICIES_PACKAGES.some( ({ name }) => name === packageInfo.name - ); + ) + ? true + : undefined; const created = await savedObjectsClient.create( PACKAGES_SAVED_OBJECT_TYPE, diff --git a/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts b/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts index b27248a3cb933..7ccfeb4fe7641 100644 --- a/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts +++ b/x-pack/plugins/fleet/server/services/managed_package_policies.test.ts @@ -8,7 +8,6 @@ import { elasticsearchServiceMock, savedObjectsClientMock } from 'src/core/server/mocks'; import type { Installation, PackageInfo } from '../../common'; -import { AUTO_UPDATE_PACKAGES } from '../../common'; import { shouldUpgradePolicies, upgradeManagedPackagePolicies } from './managed_package_policies'; import { packagePolicyService } from './package_policy'; @@ -227,50 +226,6 @@ describe('upgradeManagedPackagePolicies', () => { }); describe('shouldUpgradePolicies', () => { - describe('package is marked as AUTO_UPDATE', () => { - describe('keep_policies_up_to_date is true', () => { - it('returns false', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: true, - name: AUTO_UPDATE_PACKAGES[0].name, - }; - - const installedPackage = { - version: '1.0.0', - }; - - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); - - expect(result).toBe(false); - }); - }); - - describe('keep_policies_up_to_date is false', () => { - it('returns false', () => { - const packageInfo = { - version: '1.0.0', - keepPoliciesUpToDate: false, - name: AUTO_UPDATE_PACKAGES[0].name, - }; - - const installedPackage = { - version: '1.0.0', - }; - - const result = shouldUpgradePolicies( - packageInfo as PackageInfo, - installedPackage as Installation - ); - - expect(result).toBe(false); - }); - }); - }); - describe('package policy is up-to-date', () => { describe('keep_policies_up_to_date is true', () => { it('returns false', () => { diff --git a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap b/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap index 04d189b5d59b2..5eb4ae1808d7b 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap +++ b/x-pack/test/fleet_api_integration/apis/epm/__snapshots__/install_by_upload.snap @@ -446,7 +446,6 @@ Object { "type": "search", }, ], - "keep_policies_up_to_date": false, "name": "apache", "package_assets": Array [ Object { diff --git a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts index f3f036107fc22..0915af7e25f0c 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/install_remove_assets.ts @@ -673,7 +673,6 @@ const expectAssetsInstalled = ({ install_status: 'installed', install_started_at: res.attributes.install_started_at, install_source: 'registry', - keep_policies_up_to_date: false, }); }); }; diff --git a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts index d55f6aad53aa2..357345777e52e 100644 --- a/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts +++ b/x-pack/test/fleet_api_integration/apis/epm/update_assets.ts @@ -462,7 +462,6 @@ export default function (providerContext: FtrProviderContext) { install_status: 'installed', install_started_at: res.attributes.install_started_at, install_source: 'registry', - keep_policies_up_to_date: false, }); }); });