-
Notifications
You must be signed in to change notification settings - Fork 8.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[UII] Restrict agentless integrations to deployments with agentless e…
…nabled (#194885) ## Summary Resolves #192486. This PR makes it so that on deployments without agentless enabled: 1. Agentless-only integrations are hidden from the browse integration UI 2. Agentless-only integrations cannot be installed via API (unless force flag is used)⚠️ elastic/package-registry#1238 needs to be completed for the below testing steps to work. Currently EPR does not return `deployment_modes` property which is necessary for Fleet to know which packages are agentless. ## How to test 1. Simulate agentless being available by adding the following to kibana.yml: ``` xpack.fleet.agentless.enabled: true # Simulate cloud xpack.cloud.id: "foo" xpack.cloud.base_url: "https://cloud.elastic.co" xpack.cloud.organization_url: "/account/" xpack.cloud.billing_url: "/billing/" xpack.cloud.profile_url: "/user/settings/" ``` 2. Go to `Integrations > Browse` and enable showing Beta integrations, search for `connector` and you should see the agentless integrations: Elastic Connectors, GitHub & GitHub Enterprise Server Connector, Google Drive Connector 3. Install any one of them (they all come from the same package), it should be successful 4. Uninstall them 5. Remove config changes to go back to a non-agentless deployment 6. Refresh Integrations list, the three integrations should no longer appear 7. Try installing via API, an error should appear ``` POST kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2 ``` 8. Try installing via API again with force flag, it should be successful: ``` POST kbn:/api/fleet/epm/packages/elastic_connectors/0.0.2 { "force": true } ``` ### 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
Showing
14 changed files
with
488 additions
and
27 deletions.
There are no files selected for viewing
287 changes: 287 additions & 0 deletions
287
x-pack/plugins/fleet/common/services/agentless_policy_helper.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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); | ||
}); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.