Skip to content

Commit

Permalink
[Fleet] hide changing agent policies when editing agentless integrati…
Browse files Browse the repository at this point in the history
…on policy (elastic#190391)

## Summary

Related to elastic#183863

Follow up from
elastic#189934 (comment)

Since the edit integration was re-enabled for agentless integration
policies, we have to make sure to hide the agent policy change option
when editing an agentless policy. This pr addresses that.

To verify:
- add CSPM integration with agentless setup technology
- edit the integration policy
- verify that the agent policies can't be modified
- upload another agentless package (instruction
[here](elastic#189612))
- add Agentless integration with setup technology agentless
- edit the integration policly
- verify that the agent policies can't be modified

<img width="1526" alt="image"
src="https://github.com/user-attachments/assets/557cc6d4-37e7-43f6-b52a-3d5f4c073e1c">
<img width="1524" alt="image"
src="https://github.com/user-attachments/assets/e890efa8-4faf-4608-9228-32debadb895a">


### Checklist

- [x] [Unit or functional
tests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)
were updated or added to match the most common scenarios
  • Loading branch information
juliaElastic authored Aug 14, 2024
1 parent 0e18fb3 commit 9cb49ea
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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: {
Expand All @@ -232,7 +260,6 @@ describe('useSetupTechnology', () => {
} as any);
(useStartServices as MockFn).mockReturnValue({
cloud: {
// isServerlessEnabled: false,
isCloudEnabled: true,
},
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ export function useSetupTechnology({
packageInfo,
packagePolicy,
isEditPage,
agentPolicies,
}: {
setNewAgentPolicy: (policy: NewAgentPolicy) => void;
newAgentPolicy: NewAgentPolicy;
Expand All @@ -87,6 +88,7 @@ export function useSetupTechnology({
packageInfo?: PackageInfo;
packagePolicy: NewPackagePolicy;
isEditPage?: boolean;
agentPolicies?: AgentPolicy[];
}) {
const { isAgentlessEnabled, isAgentlessCloudEnabled, isAgentlessServerlessEnabled } =
useAgentless();
Expand All @@ -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) {
Expand All @@ -126,6 +129,8 @@ export function useSetupTechnology({
selectedSetupTechnology,
updateAgentPolicies,
setNewAgentPolicy,
agentPolicies,
setSelectedSetupTechnology,
]);

// tech debt: remove this useEffect when Serverless uses the Agentless API
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ export function usePackagePolicySteps({
packageInfo,
packagePolicy,
isEditPage: true,
agentPolicies,
});

const stepSelectAgentPolicy = useMemo(
Expand Down
20 changes: 20 additions & 0 deletions x-pack/plugins/fleet/server/routes/package_policy/handlers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 () => {
Expand Down Expand Up @@ -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({
Expand Down
15 changes: 14 additions & 1 deletion x-pack/plugins/fleet/server/routes/package_policy/handlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -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(
Expand Down

0 comments on commit 9cb49ea

Please sign in to comment.