diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts index 9edca8f772fbac..f32ea1cd007cee 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.test.ts @@ -221,6 +221,34 @@ describe('useSetupTechnology', () => { expect(sendGetOneAgentPolicy).toHaveBeenCalled(); }); + it('should set agentless setup technology if agent policy supports agentless in edit page', async () => { + (useConfig as MockFn).mockReturnValue({ + agentless: { + api: { + url: 'https://agentless.api.url', + }, + }, + } as any); + (useStartServices as MockFn).mockReturnValue({ + cloud: { + isCloudEnabled: true, + }, + }); + const { result } = renderHook(() => + useSetupTechnology({ + setNewAgentPolicy, + newAgentPolicy: newAgentPolicyMock, + updateAgentPolicies: updateAgentPoliciesMock, + setSelectedPolicyTab: setSelectedPolicyTabMock, + packagePolicy: packagePolicyMock, + isEditPage: true, + agentPolicies: [{ id: 'agentless-policy-id', supports_agentless: true } as any], + }) + ); + + expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS); + }); + it('should create agentless policy if agentless feature is enabled and isCloud is true and agentless.api.url', async () => { (useConfig as MockFn).mockReturnValue({ agentless: { @@ -232,7 +260,6 @@ describe('useSetupTechnology', () => { } as any); (useStartServices as MockFn).mockReturnValue({ cloud: { - // isServerlessEnabled: false, isCloudEnabled: true, }, }); diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts index 078fb51ebf3767..7fc159a2d43481 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/create_package_policy_page/single_page_layout/hooks/setup_technology.ts @@ -79,6 +79,7 @@ export function useSetupTechnology({ packageInfo, packagePolicy, isEditPage, + agentPolicies, }: { setNewAgentPolicy: (policy: NewAgentPolicy) => void; newAgentPolicy: NewAgentPolicy; @@ -87,6 +88,7 @@ export function useSetupTechnology({ packageInfo?: PackageInfo; packagePolicy: NewPackagePolicy; isEditPage?: boolean; + agentPolicies?: AgentPolicy[]; }) { const { isAgentlessEnabled, isAgentlessCloudEnabled, isAgentlessServerlessEnabled } = useAgentless(); @@ -104,7 +106,8 @@ export function useSetupTechnology({ ); useEffect(() => { - if (isEditPage) { + if (isEditPage && agentPolicies && agentPolicies.some((policy) => policy.supports_agentless)) { + setSelectedSetupTechnology(SetupTechnology.AGENTLESS); return; } if (isAgentlessCloudEnabled && selectedSetupTechnology === SetupTechnology.AGENTLESS) { @@ -126,6 +129,8 @@ export function useSetupTechnology({ selectedSetupTechnology, updateAgentPolicies, setNewAgentPolicy, + agentPolicies, + setSelectedSetupTechnology, ]); // tech debt: remove this useEffect when Serverless uses the Agentless API diff --git a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx index dd349fca9909e4..5acd854a76f046 100644 --- a/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx +++ b/x-pack/plugins/fleet/public/applications/fleet/sections/agent_policy/edit_package_policy_page/hooks/use_package_policy_steps.tsx @@ -145,6 +145,7 @@ export function usePackagePolicySteps({ packageInfo, packagePolicy, isEditPage: true, + agentPolicies, }); const stepSelectAgentPolicy = useMemo( diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts index 9cefa2581629f0..f42ed003600339 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts @@ -311,6 +311,7 @@ describe('When calling package policy', () => { }, ], }); + (agentPolicyService.get as jest.Mock).mockResolvedValue({ inputs: [] }); }); it('should use existing package policy props if not provided by request', async () => { @@ -371,6 +372,25 @@ describe('When calling package policy', () => { }); }); + it('should throw if policy_ids changed on agentless integration', async () => { + (agentPolicyService.get as jest.Mock).mockResolvedValue({ + supports_agentless: true, + inputs: [], + }); + jest.spyOn(licenseService, 'hasAtLeast').mockReturnValue(true); + jest + .spyOn(appContextService, 'getExperimentalFeatures') + .mockReturnValue({ enableReusableIntegrationPolicies: true } as any); + const request = getUpdateKibanaRequest({ policy_ids: ['1', '2'] } as any); + await routeHandler(context, request, response); + expect(response.customError).toHaveBeenCalledWith({ + statusCode: 400, + body: { + message: 'Cannot change agent policies of an agentless integration', + }, + }); + }); + it('should rename the agentless agent policy to sync with the package policy name if agentless is enabled', async () => { jest.spyOn(appContextService, 'getCloud').mockReturnValue({ isCloudEnabled: true } as any); jest.spyOn(appContextService, 'getConfig').mockReturnValue({ diff --git a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts index 31e38125dead5d..5cc00ef014cdeb 100644 --- a/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts +++ b/x-pack/plugins/fleet/server/routes/package_policy/handlers.ts @@ -10,7 +10,7 @@ import type { TypeOf } from '@kbn/config-schema'; import { SavedObjectsErrorHelpers } from '@kbn/core/server'; import type { RequestHandler } from '@kbn/core/server'; -import { groupBy, keyBy } from 'lodash'; +import { groupBy, isEmpty, isEqual, keyBy } from 'lodash'; import { HTTPAuthorizationHeader } from '../../../common/http_authorization_header'; @@ -410,6 +410,19 @@ export const updatePackagePolicyHandler: FleetRequestHandler< throw new PackagePolicyRequestError('At least one agent policy id must be provided'); } + if ( + newData.policy_ids && + !isEmpty(packagePolicy.policy_ids) && + !isEqual(newData.policy_ids, packagePolicy.policy_ids) + ) { + const agentPolicy = await agentPolicyService.get(soClient, packagePolicy.policy_ids[0]); + if (agentPolicy?.supports_agentless) { + throw new PackagePolicyRequestError( + 'Cannot change agent policies of an agentless integration' + ); + } + } + await renameAgentlessAgentPolicy(soClient, esClient, packagePolicy, newData.name); const updatedPackagePolicy = await packagePolicyService.update(