Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,58 @@ describe('agentless_policy_helper', () => {

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

it('should return true if the specified integration supports agentless', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
deployment_modes: {
agentless: { enabled: true },
default: { enabled: false },
},
},
{
name: 'template2',
deployment_modes: {
agentless: { enabled: false },
default: { enabled: true },
},
},
] as RegistryPolicyTemplate[],
};

expect(isAgentlessIntegration(packageInfo, 'template1')).toBe(true);
expect(isAgentlessIntegration(packageInfo, 'template2')).toBe(false);
});

it('should return false if the specified integration does not exist', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
deployment_modes: {
agentless: { enabled: true },
default: { enabled: false },
},
},
] as RegistryPolicyTemplate[],
};

expect(isAgentlessIntegration(packageInfo, 'nonexistent')).toBe(false);
});

it('should return false if the specified integration exists but has no deployment_modes', () => {
const packageInfo = {
policy_templates: [
{
name: 'template1',
},
] as RegistryPolicyTemplate[],
};

expect(isAgentlessIntegration(packageInfo, 'template1')).toBe(false);
});
});

describe('getAgentlessAgentPolicyNameFromPackagePolicyName', () => {
Expand Down Expand Up @@ -331,6 +383,11 @@ describe('agentless_policy_helper', () => {
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
inputs: [
{ type: 'logs', deployment_modes: ['default', 'agentless'] },
{ type: 'metrics', deployment_modes: ['default'] },
Expand All @@ -340,6 +397,11 @@ describe('agentless_policy_helper', () => {
name: 'template2',
title: 'Template 2',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
inputs: [
{ type: 'logs', deployment_modes: ['agentless'] },
{ type: 'tcp', deployment_modes: ['default'] },
Expand Down Expand Up @@ -368,6 +430,82 @@ describe('agentless_policy_helper', () => {
).toBe(true);
});

it('should return false for input without a policy_template deployment_mode enabled for agentless when the requested mode is agentless', () => {
const packageInfoWithoutPolicyTemplateDeploymentModes = {
name: 'test-package',
version: '1.0.0',
owner: { github: 'elastic' },
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
inputs: [{ type: 'metrics', deployment_modes: ['agentless', 'default'] }],
},
] as RegistryPolicyTemplate[],
} as any;
const input = { type: 'metrics', policy_template: 'template1' };
expect(
isInputAllowedForDeploymentMode(
input,
'agentless',
packageInfoWithoutPolicyTemplateDeploymentModes
)
).toBe(false);
});

it('should return false for input with a policy_template deployment mode that overrides the requested mode', () => {
const packageInfoWithPolicyTemplateOverride = {
name: 'test-package',
version: '1.0.0',
owner: { github: 'elastic' },
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
agentless: {
enabled: false,
},
default: {
enabled: false,
},
},
inputs: [{ type: 'metrics', deployment_modes: ['agentless', 'default'] }],
},
] as RegistryPolicyTemplate[],
} as any;
const input = { type: 'metrics', policy_template: 'template1' };
expect(
isInputAllowedForDeploymentMode(input, 'agentless', packageInfoWithPolicyTemplateOverride)
).toBe(false);

expect(
isInputAllowedForDeploymentMode(input, 'default', packageInfoWithPolicyTemplateOverride)
).toBe(false);
});

it('should return true for input with no policy template or input deployment mode defined when requested mode is default ', () => {
const packageInfoWithPolicyTemplateOverride = {
name: 'test-package',
version: '1.0.0',
owner: { github: 'elastic' },
policy_templates: [
{
name: 'template1',
title: 'Template 1',
description: '',
inputs: [{ type: 'metrics' }],
},
] as RegistryPolicyTemplate[],
} as any;
const input = { type: 'metrics', policy_template: 'template1' };
expect(
isInputAllowedForDeploymentMode(input, 'default', packageInfoWithPolicyTemplateOverride)
).toBe(true);
});

it('should handle inputs with different deployment_modes under different policy templates', () => {
const input1 = { type: 'logs', policy_template: 'template1' };
const input2 = { type: 'logs', policy_template: 'template2' };
Expand All @@ -390,6 +528,11 @@ describe('agentless_policy_helper', () => {
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
inputs: [{ type: 'log' }, { type: 'winlog' }],
},
] as RegistryPolicyTemplate[],
Expand Down Expand Up @@ -502,6 +645,11 @@ describe('agentless_policy_helper', () => {
name: 'template1',
title: 'Template 1',
description: '',
deployment_modes: {
agentless: {
enabled: true,
},
},
inputs: [
{ type: 'logs', deployment_modes: ['default', 'agentless'] },
{ type: 'metrics', deployment_modes: ['default'] },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,19 +46,24 @@ function extractRegistryInputsForDeploymentMode(
return inputs;
}

// Checks if a package has a policy template that supports agentless
// Provide a specific integration policy template name to check if it alone supports agentless
export const isAgentlessIntegration = (
packageInfo: Pick<PackageInfo, 'policy_templates'> | undefined
packageInfo: Pick<PackageInfo, 'policy_templates'> | undefined,
integrationToEnable?: string
) => {
if (
packageInfo?.policy_templates &&
packageInfo?.policy_templates.length > 0 &&
!!packageInfo?.policy_templates.find(
(policyTemplate) => policyTemplate?.deployment_modes?.agentless.enabled === true
)
) {
return true;
if (integrationToEnable) {
return Boolean(
packageInfo?.policy_templates?.find(({ name }) => name === integrationToEnable)
?.deployment_modes?.agentless?.enabled === true
);
}
return false;

return Boolean(
packageInfo?.policy_templates?.some(
(policyTemplate) => policyTemplate?.deployment_modes?.agentless?.enabled === true
)
);
};

export const getAgentlessAgentPolicyNameFromPackagePolicyName = (packagePolicyName: string) => {
Expand Down Expand Up @@ -108,6 +113,15 @@ export function isInputAllowedForDeploymentMode(
return true;
}

// Check first if policy_template for input supports the deployment type
if (
packageInfo &&
input.policy_template &&
!integrationSupportsDeploymentMode(deploymentMode, packageInfo, input.policy_template)
) {
return false;
}

// Find the registry input definition for this input type and policy template
const registryInput = extractRegistryInputsForDeploymentMode(packageInfo).find(
(rInput) =>
Expand All @@ -130,6 +144,24 @@ export function isInputAllowedForDeploymentMode(
return true; // Allow all inputs for default mode when deployment_modes is not specified
}

const integrationSupportsDeploymentMode = (
deploymentMode: string,
packageInfo: PackageInfo,
integrationName: string
) => {
if (deploymentMode === 'agentless') {
return isAgentlessIntegration(packageInfo, integrationName);
}

const integration = packageInfo.policy_templates?.find(({ name }) => name === integrationName);

if (integration?.deployment_modes?.default) {
return integration.deployment_modes?.default.enabled;
}

return true;
};

/*
* Throw error if trying to enabling an input that is not allowed in agentless
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,7 @@ import { validatePackagePolicy } from '../../services';

import { StepConfigurePackagePolicy } from './step_configure_package';

// FLAKY: https://github.com/elastic/kibana/issues/201598
describe.skip('StepConfigurePackage', () => {
describe('StepConfigurePackage', () => {
let packageInfo: PackageInfo;
let packagePolicy: NewPackagePolicy;
const mockUpdatePackagePolicy = jest.fn().mockImplementation((val: any) => {
Expand All @@ -30,7 +29,7 @@ describe.skip('StepConfigurePackage', () => {

let testRenderer: TestRenderer;
let renderResult: ReturnType<typeof testRenderer.render>;
const render = () => {
const render = (isAgentlessSelected = false) => {
const validationResults = validatePackagePolicy(packagePolicy, packageInfo, load);

renderResult = testRenderer.render(
Expand All @@ -40,6 +39,7 @@ describe.skip('StepConfigurePackage', () => {
updatePackagePolicy={mockUpdatePackagePolicy}
validationResults={validationResults}
submitAttempted={false}
isAgentlessSelected={isAgentlessSelected}
/>
);
};
Expand Down Expand Up @@ -68,6 +68,23 @@ describe.skip('StepConfigurePackage', () => {
],
multiple: true,
},
{
name: 'agentless_supported',
title: 'Agentless Supported',
description: 'Collect endpoint health the agentless way',
deployment_modes: {
default: { enabled: false },
agentless: { enabled: true },
},
inputs: [
{
type: 'httpjson',
title: 'Some agentless input',
description: 'Collect endpoint health the agentless way',
},
],
multiple: true,
},
],
data_streams: [
{
Expand Down Expand Up @@ -111,6 +128,7 @@ describe.skip('StepConfigurePackage', () => {
policy_id: '',
policy_ids: [''],
enabled: true,
supports_agentless: true,
inputs: [
{
type: 'logfile',
Expand All @@ -129,6 +147,20 @@ describe.skip('StepConfigurePackage', () => {
},
],
},
{
type: 'httpjson',
policy_template: 'agentless_supported',
enabled: true,
streams: [
{
enabled: true,
data_stream: { type: 'http', dataset: 'nginx.access' },
vars: {
url: { value: 'http://localhost:8080', type: 'text' },
},
},
],
},
],
};
testRenderer = createFleetTestRendererMock();
Expand Down Expand Up @@ -169,4 +201,19 @@ describe.skip('StepConfigurePackage', () => {
).toBeInTheDocument();
});
});

it('renders only agentless-supported policy templates when agentless is selected', async () => {
render(true);
expect(renderResult.queryByText('Some agentless input')).toBeInTheDocument();
expect(
await renderResult.queryByText('Collect logs from Nginx instances')
).not.toBeInTheDocument();
});

it('renders all non-agentless policy templates when agentless is not selected', async () => {
render();

expect(await renderResult.queryByText('Collect logs from Nginx instances')).toBeInTheDocument();
expect(await renderResult.queryByText('Some agentless input')).not.toBeInTheDocument();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ export const StepConfigurePackagePolicy: React.FunctionComponent<{
isAgentlessSelected = false,
}) => {
const hasIntegrations = useMemo(() => doesPackageHaveIntegrations(packageInfo), [packageInfo]);
const deploymentMode =
(isEditPage || isAgentlessSelected) && packagePolicy.supports_agentless
? 'agentless'
: 'default';
const packagePolicyTemplates = useMemo(
() =>
showOnlyIntegration
Expand Down Expand Up @@ -102,11 +106,7 @@ export const StepConfigurePackagePolicy: React.FunctionComponent<{

const isInputAvailable =
packagePolicyInput &&
isInputAllowedForDeploymentMode(
packagePolicyInput,
isAgentlessSelected && packagePolicy.supports_agentless ? 'agentless' : 'default',
packageInfo
);
isInputAllowedForDeploymentMode(packagePolicyInput, deploymentMode, packageInfo);

return isInputAvailable ? (
<EuiFlexItem key={packageInput.type}>
Expand Down
Loading
Loading