Skip to content

Commit

Permalink
[8.x] [UII] Restrict agentless integrations to deployments with agent…
Browse files Browse the repository at this point in the history
…less enabled (#194885) (#196459)

# Backport

This will backport the following commits from `main` to `8.x`:
- [[UII] Restrict agentless integrations to deployments with agentless
enabled (#194885)](#194885)

<!--- Backport version: 9.4.3 -->

### Questions ?
Please refer to the [Backport tool
documentation](https://github.com/sqren/backport)

<!--BACKPORT [{"author":{"name":"Jen
Huang","email":"[email protected]"},"sourceCommit":{"committedDate":"2024-10-15T23:57:32Z","message":"[UII]
Restrict agentless integrations to deployments with agentless enabled
(#194885)\n\n## Summary\r\n\r\nResolves #192486. This PR makes it so
that on deployments without\r\nagentless enabled:\r\n1. Agentless-only
integrations are hidden from the browse integration UI\r\n2.
Agentless-only integrations cannot be installed via API (unless
force\r\nflag is used)\r\n\r\n⚠️
elastic/package-registry#1238 needs to
be\r\ncompleted for the below testing steps to work. Currently EPR does
not\r\nreturn `deployment_modes` property which is necessary for Fleet
to know\r\nwhich packages are agentless.\r\n\r\n## How to test\r\n\r\n1.
Simulate agentless being available by adding the following
to\r\nkibana.yml:\r\n```\r\nxpack.fleet.agentless.enabled: true\r\n\r\n#
Simulate cloud\r\nxpack.cloud.id: \"foo\"\r\nxpack.cloud.base_url:
\"https://cloud.elastic.co\"\r\nxpack.cloud.organization_url:
\"/account/\"\r\nxpack.cloud.billing_url:
\"/billing/\"\r\nxpack.cloud.profile_url:
\"/user/settings/\"\r\n```\r\n2. Go to `Integrations > Browse` and
enable showing Beta integrations,\r\nsearch for `connector` and you
should see the agentless integrations:\r\nElastic Connectors, GitHub &
GitHub Enterprise Server Connector, Google\r\nDrive Connector\r\n3.
Install any one of them (they all come from the same package),
it\r\nshould be successful\r\n4. Uninstall them\r\n5. Remove config
changes to go back to a non-agentless deployment\r\n6. Refresh
Integrations list, the three integrations should no
longer\r\nappear\r\n7. Try installing via API, an error should
appear\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n```\r\n8. Try
installing via API again with force flag, it should
be\r\nsuccessful:\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n{\r\n \"force\":
true\r\n}\r\n```\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"8cadf88c66a257c073279fa11572b089c32eb643","branchLabelMapping":{"^v9.0.0$":"main","^v8.16.0$":"8.x","^v(\\d+).(\\d+).\\d+$":"$1.$2"}},"sourcePullRequest":{"labels":["release_note:skip","Team:Fleet","v9.0.0","backport:prev-minor"],"title":"[UII]
Restrict agentless integrations to deployments with agentless
enabled","number":194885,"url":"https://github.com/elastic/kibana/pull/194885","mergeCommit":{"message":"[UII]
Restrict agentless integrations to deployments with agentless enabled
(#194885)\n\n## Summary\r\n\r\nResolves #192486. This PR makes it so
that on deployments without\r\nagentless enabled:\r\n1. Agentless-only
integrations are hidden from the browse integration UI\r\n2.
Agentless-only integrations cannot be installed via API (unless
force\r\nflag is used)\r\n\r\n⚠️
elastic/package-registry#1238 needs to
be\r\ncompleted for the below testing steps to work. Currently EPR does
not\r\nreturn `deployment_modes` property which is necessary for Fleet
to know\r\nwhich packages are agentless.\r\n\r\n## How to test\r\n\r\n1.
Simulate agentless being available by adding the following
to\r\nkibana.yml:\r\n```\r\nxpack.fleet.agentless.enabled: true\r\n\r\n#
Simulate cloud\r\nxpack.cloud.id: \"foo\"\r\nxpack.cloud.base_url:
\"https://cloud.elastic.co\"\r\nxpack.cloud.organization_url:
\"/account/\"\r\nxpack.cloud.billing_url:
\"/billing/\"\r\nxpack.cloud.profile_url:
\"/user/settings/\"\r\n```\r\n2. Go to `Integrations > Browse` and
enable showing Beta integrations,\r\nsearch for `connector` and you
should see the agentless integrations:\r\nElastic Connectors, GitHub &
GitHub Enterprise Server Connector, Google\r\nDrive Connector\r\n3.
Install any one of them (they all come from the same package),
it\r\nshould be successful\r\n4. Uninstall them\r\n5. Remove config
changes to go back to a non-agentless deployment\r\n6. Refresh
Integrations list, the three integrations should no
longer\r\nappear\r\n7. Try installing via API, an error should
appear\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n```\r\n8. Try
installing via API again with force flag, it should
be\r\nsuccessful:\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n{\r\n \"force\":
true\r\n}\r\n```\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"8cadf88c66a257c073279fa11572b089c32eb643"}},"sourceBranch":"main","suggestedTargetBranches":[],"targetPullRequestStates":[{"branch":"main","label":"v9.0.0","branchLabelMappingKey":"^v9.0.0$","isSourceBranch":true,"state":"MERGED","url":"https://github.com/elastic/kibana/pull/194885","number":194885,"mergeCommit":{"message":"[UII]
Restrict agentless integrations to deployments with agentless enabled
(#194885)\n\n## Summary\r\n\r\nResolves #192486. This PR makes it so
that on deployments without\r\nagentless enabled:\r\n1. Agentless-only
integrations are hidden from the browse integration UI\r\n2.
Agentless-only integrations cannot be installed via API (unless
force\r\nflag is used)\r\n\r\n⚠️
elastic/package-registry#1238 needs to
be\r\ncompleted for the below testing steps to work. Currently EPR does
not\r\nreturn `deployment_modes` property which is necessary for Fleet
to know\r\nwhich packages are agentless.\r\n\r\n## How to test\r\n\r\n1.
Simulate agentless being available by adding the following
to\r\nkibana.yml:\r\n```\r\nxpack.fleet.agentless.enabled: true\r\n\r\n#
Simulate cloud\r\nxpack.cloud.id: \"foo\"\r\nxpack.cloud.base_url:
\"https://cloud.elastic.co\"\r\nxpack.cloud.organization_url:
\"/account/\"\r\nxpack.cloud.billing_url:
\"/billing/\"\r\nxpack.cloud.profile_url:
\"/user/settings/\"\r\n```\r\n2. Go to `Integrations > Browse` and
enable showing Beta integrations,\r\nsearch for `connector` and you
should see the agentless integrations:\r\nElastic Connectors, GitHub &
GitHub Enterprise Server Connector, Google\r\nDrive Connector\r\n3.
Install any one of them (they all come from the same package),
it\r\nshould be successful\r\n4. Uninstall them\r\n5. Remove config
changes to go back to a non-agentless deployment\r\n6. Refresh
Integrations list, the three integrations should no
longer\r\nappear\r\n7. Try installing via API, an error should
appear\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n```\r\n8. Try
installing via API again with force flag, it should
be\r\nsuccessful:\r\n```\r\nPOST
kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2\r\n{\r\n \"force\":
true\r\n}\r\n```\r\n\r\n### Checklist\r\n\r\n- [x] [Unit or
functional\r\ntests](https://www.elastic.co/guide/en/kibana/master/development-tests.html)\r\nwere
updated or added to match the most common
scenarios","sha":"8cadf88c66a257c073279fa11572b089c32eb643"}}]}]
BACKPORT-->

Co-authored-by: Jen Huang <[email protected]>
  • Loading branch information
kibanamachine and jen-huang authored Oct 16, 2024
1 parent b9820cc commit 34b0772
Show file tree
Hide file tree
Showing 14 changed files with 488 additions and 27 deletions.
287 changes: 287 additions & 0 deletions x-pack/plugins/fleet/common/services/agentless_policy_helper.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,287 @@
/*
* 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 type { RegistryPolicyTemplate } from '../types';

import {
isAgentlessIntegration,
getAgentlessAgentPolicyNameFromPackagePolicyName,
isOnlyAgentlessIntegration,
isOnlyAgentlessPolicyTemplate,
} from './agentless_policy_helper';

describe('agentless_policy_helper', () => {
describe('isAgentlessIntegration', () => {
it('should return true if packageInfo is defined and has at least one agentless integration', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: true,
},
agentless: {
enabled: true,
},
},
},
{
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
default: {
enabled: true,
},
},
},
] as RegistryPolicyTemplate[],
};

const result = isAgentlessIntegration(packageInfo);

expect(result).toBe(true);
});

it('should return false if packageInfo is defined but does not have agentless integrations', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: true,
},
agentless: {
enabled: false,
},
},
},
{
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
default: {
enabled: false,
},
agentless: {
enabled: false,
},
},
},
] as RegistryPolicyTemplate[],
};

const result = isAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});

it('should return false if packageInfo has no policy templates', () => {
const packageInfo = {
policy_templates: [],
};

const result = isAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});

it('should return false if packageInfo is undefined', () => {
const packageInfo = undefined;

const result = isAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});
});

describe('getAgentlessAgentPolicyNameFromPackagePolicyName', () => {
it('should return the agentless agent policy name based on the package policy name', () => {
const packagePolicyName = 'example-package-policy';

const result = getAgentlessAgentPolicyNameFromPackagePolicyName(packagePolicyName);

expect(result).toBe('Agentless policy for example-package-policy');
});
});

describe('isOnlyAgentlessIntegration', () => {
it('should return true if packageInfo is defined and has only agentless integration', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: false,
},
agentless: {
enabled: true,
},
},
},
{
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
},
] as RegistryPolicyTemplate[],
};

const result = isOnlyAgentlessIntegration(packageInfo);

expect(result).toBe(true);
});

it('should return false if packageInfo is defined but has other deployment types', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: true,
},
agentless: {
enabled: true,
},
},
},
{
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
default: {
enabled: true,
},
},
},
] as RegistryPolicyTemplate[],
};

const result = isOnlyAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});

it('should return false if packageInfo has no policy templates', () => {
const packageInfo = {
policy_templates: [],
};

const result = isOnlyAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});

it('should return false if packageInfo is undefined', () => {
const packageInfo = undefined;

const result = isOnlyAgentlessIntegration(packageInfo);

expect(result).toBe(false);
});
});

describe('isOnlyAgentlessPolicyTemplate', () => {
it('should return true if the policy template is only agentless', () => {
const policyTemplate = {
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: false,
},
agentless: {
enabled: true,
},
},
};
const policyTemplate2 = {
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
};

const result = isOnlyAgentlessPolicyTemplate(policyTemplate);
const result2 = isOnlyAgentlessPolicyTemplate(policyTemplate2);

expect(result).toBe(true);
expect(result2).toBe(true);
});

it('should return false if the policy template has other deployment types', () => {
const policyTemplate = {
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
default: {
enabled: true,
},
agentless: {
enabled: true,
},
},
};
const policyTemplate2 = {
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
default: {
enabled: true,
},
agentless: {
enabled: false,
},
},
};

const result = isOnlyAgentlessPolicyTemplate(policyTemplate);
const result2 = isOnlyAgentlessPolicyTemplate(policyTemplate2);

expect(result).toBe(false);
expect(result2).toBe(false);
});

it('should return false if the policy template has no deployment modes', () => {
const policyTemplate = {
name: 'template1',
title: 'Template 1',
description: '',
};

const result = isOnlyAgentlessPolicyTemplate(policyTemplate);

expect(result).toBe(false);
});
});
});
41 changes: 41 additions & 0 deletions x-pack/plugins/fleet/common/services/agentless_policy_helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,47 @@
* 2.0.
*/

import type { PackageInfo, RegistryPolicyTemplate } from '../types';

export const isAgentlessIntegration = (
packageInfo: Pick<PackageInfo, 'policy_templates'> | undefined
) => {
if (
packageInfo?.policy_templates &&
packageInfo?.policy_templates.length > 0 &&
!!packageInfo?.policy_templates.find(
(policyTemplate) => policyTemplate?.deployment_modes?.agentless.enabled === true
)
) {
return true;
}
return false;
};

export const getAgentlessAgentPolicyNameFromPackagePolicyName = (packagePolicyName: string) => {
return `Agentless policy for ${packagePolicyName}`;
};

export const isOnlyAgentlessIntegration = (
packageInfo: Pick<PackageInfo, 'policy_templates'> | undefined
) => {
if (
packageInfo?.policy_templates &&
packageInfo?.policy_templates.length > 0 &&
packageInfo?.policy_templates.every((policyTemplate) =>
isOnlyAgentlessPolicyTemplate(policyTemplate)
)
) {
return true;
}
return false;
};

export const isOnlyAgentlessPolicyTemplate = (policyTemplate: RegistryPolicyTemplate) => {
return Boolean(
policyTemplate.deployment_modes &&
policyTemplate.deployment_modes.agentless.enabled === true &&
(!policyTemplate.deployment_modes.default ||
policyTemplate.deployment_modes.default.enabled === false)
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ import { SetupTechnology } from '../../../../../types';
import { sendGetOneAgentPolicy, useStartServices } from '../../../../../hooks';
import { SelectedPolicyTab } from '../../components';
import { AGENTLESS_POLICY_ID } from '../../../../../../../../common/constants';
import { getAgentlessAgentPolicyNameFromPackagePolicyName } from '../../../../../../../../common/services/agentless_policy_helper';
import {
isAgentlessIntegration as isAgentlessIntegrationFn,
getAgentlessAgentPolicyNameFromPackagePolicyName,
} from '../../../../../../../../common/services/agentless_policy_helper';

export const useAgentless = () => {
const config = useConfig();
Expand All @@ -45,14 +48,7 @@ export const useAgentless = () => {

// When an integration has at least a policy template enabled for agentless
const isAgentlessIntegration = (packageInfo: PackageInfo | undefined) => {
if (
isAgentlessEnabled &&
packageInfo?.policy_templates &&
packageInfo?.policy_templates.length > 0 &&
!!packageInfo?.policy_templates.find(
(policyTemplate) => policyTemplate?.deployment_modes?.agentless.enabled === true
)
) {
if (isAgentlessEnabled && isAgentlessIntegrationFn(packageInfo)) {
return true;
}
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,6 @@ export function usePackagePolicySteps({
setNewAgentPolicy,
updateAgentPolicies,
setSelectedPolicyTab,
packageInfo,
packagePolicy,
isEditPage: true,
agentPolicies,
Expand Down
Loading

0 comments on commit 34b0772

Please sign in to comment.