mirror of
https://github.com/elastic/kibana.git
synced 2025-04-24 17:59:23 -04:00
[UII] Support is_default
on integration deployment modes (#208284)
## Summary Resolves #205761 Resolves https://github.com/elastic/security-team/issues/10712 This PR adds support for `is_default` property for integration deployment modes, so that if an integration declares agentless to be the default deployment mode, the policy editor will select `Agentless` by default when adding it: <img width="1422" alt="image" src="https://github.com/user-attachments/assets/74c7c8fa-2df9-4e03-bb2b-aa192927aa6d" /> ## Testing 1. Check out `integrations` repo 2. Apply [cspm-patch.diff](https://gist.github.com/jen-huang/8574262ea2e5fb8b1c3a134d2b4263d5) 3. In `packages/cloud_security_posture/`, run `elastic-package build` (or ask Jen for the built .zip if you have trouble 😉) 4. Upload the built package in Kibana at `/app/integrations/create/upload` 5. Go to Integrations > search for CSPM > Add integration 6. Observe that Advanced options > Setup technology dropdown defaults to Agentless and agent policy selection is not offered 7. Go back to Integrations > search for Security Posture Management (parent of CSPM) > Add integration 8. Observe that CSPM is selected by default with Agentless mode selected by default as well ### Checklist Check the PR satisfies following conditions. Reviewers should verify this PR satisfies this list as well. - [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 - [x] The PR description includes the appropriate Release Notes section, and the correct `release_note:*` label is applied per the [guidelines](https://www.elastic.co/guide/en/kibana/master/contributing.html#kibana-release-notes-process)
This commit is contained in:
parent
c347582ffb
commit
2d3fc93e74
11 changed files with 427 additions and 108 deletions
|
@ -151,6 +151,40 @@ describe('agentless_policy_helper', () => {
|
|||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return true if packageInfo is defined and selected integration only has agentless', () => {
|
||||
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: {
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
] as RegistryPolicyTemplate[],
|
||||
};
|
||||
|
||||
const result = isOnlyAgentlessIntegration(packageInfo, 'template2');
|
||||
|
||||
expect(result).toBe(true);
|
||||
});
|
||||
|
||||
it('should return false if packageInfo is defined but has other deployment types', () => {
|
||||
const packageInfo = {
|
||||
policy_templates: [
|
||||
|
|
|
@ -31,14 +31,18 @@ export const getAgentlessAgentPolicyNameFromPackagePolicyName = (packagePolicyNa
|
|||
};
|
||||
|
||||
export const isOnlyAgentlessIntegration = (
|
||||
packageInfo: Pick<PackageInfo, 'policy_templates'> | undefined
|
||||
packageInfo?: Pick<PackageInfo, 'policy_templates'>,
|
||||
integrationToEnable?: string
|
||||
) => {
|
||||
if (
|
||||
packageInfo?.policy_templates &&
|
||||
packageInfo?.policy_templates.length > 0 &&
|
||||
packageInfo?.policy_templates.every((policyTemplate) =>
|
||||
isOnlyAgentlessPolicyTemplate(policyTemplate)
|
||||
)
|
||||
packageInfo &&
|
||||
packageInfo.policy_templates &&
|
||||
packageInfo.policy_templates?.length > 0 &&
|
||||
((integrationToEnable &&
|
||||
packageInfo.policy_templates?.find(
|
||||
(p) => p.name === integrationToEnable && isOnlyAgentlessPolicyTemplate(p)
|
||||
)) ||
|
||||
packageInfo.policy_templates?.every((p) => isOnlyAgentlessPolicyTemplate(p)))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -195,6 +195,7 @@ export interface RegistryImage extends PackageSpecIcon {
|
|||
|
||||
export interface DeploymentsModesDefault {
|
||||
enabled: boolean;
|
||||
is_default?: boolean;
|
||||
}
|
||||
|
||||
export interface DeploymentsModesAgentless extends DeploymentsModesDefault {
|
||||
|
|
|
@ -312,6 +312,7 @@ export function useOnSubmit({
|
|||
setSelectedPolicyTab,
|
||||
packageInfo,
|
||||
packagePolicy,
|
||||
integrationToEnable,
|
||||
});
|
||||
const setupTechnologyRef = useRef<SetupTechnology | undefined>(selectedSetupTechnology);
|
||||
// sync the inputs with the agentless selector change
|
||||
|
|
|
@ -227,18 +227,305 @@ describe('useSetupTechnology', () => {
|
|||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should initialize with default values when agentless is disabled', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
})
|
||||
);
|
||||
describe('default values', () => {
|
||||
it('should be agent-based when agentless is disabled', () => {
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
it('should be agent-based when agentless is enabled and integrations have a mix of deployment modes', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [
|
||||
{
|
||||
name: 'template1',
|
||||
title: 'Template 1',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'template2',
|
||||
title: 'Template 2',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as PackageInfo,
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
it('should be agent-based when agentless is enabled and selected integration is agent-based by default', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [
|
||||
{
|
||||
name: 'template1',
|
||||
title: 'Template 1',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'template2',
|
||||
title: 'Template 2',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
is_default: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as PackageInfo,
|
||||
integrationToEnable: 'template2',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
it('should be agent-based when packageInfo has no policy templates', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [] as PackageInfo['policy_templates'],
|
||||
} as PackageInfo,
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENT_BASED);
|
||||
});
|
||||
|
||||
it('should be agentless when agentless is enabled and all integrations are only agentless', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [
|
||||
{
|
||||
name: 'template1',
|
||||
title: 'Template 1',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: false,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'template2',
|
||||
title: 'Template 2',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: false,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as PackageInfo,
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
it('should be agentless when agentless is enabled and selected integration is only agentless', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [
|
||||
{
|
||||
name: 'template1',
|
||||
title: 'Template 1',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: false,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'template2',
|
||||
title: 'Template 2',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as PackageInfo,
|
||||
integrationToEnable: 'template1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
it('should be agentless when agentless is enabled and selected integration is agentless by default', () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
api: {
|
||||
url: 'https://agentless.api.url',
|
||||
},
|
||||
},
|
||||
} as any);
|
||||
|
||||
const { result } = renderHook(() =>
|
||||
useSetupTechnology({
|
||||
setNewAgentPolicy,
|
||||
newAgentPolicy: newAgentPolicyMock,
|
||||
setSelectedPolicyTab: setSelectedPolicyTabMock,
|
||||
packagePolicy: packagePolicyMock,
|
||||
updatePackagePolicy: updatePackagePolicyMock,
|
||||
packageInfo: {
|
||||
policy_templates: [
|
||||
{
|
||||
name: 'template1',
|
||||
title: 'Template 1',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
is_default: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'template2',
|
||||
title: 'Template 2',
|
||||
deployment_modes: {
|
||||
default: {
|
||||
enabled: true,
|
||||
},
|
||||
agentless: {
|
||||
enabled: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
} as PackageInfo,
|
||||
integrationToEnable: 'template1',
|
||||
})
|
||||
);
|
||||
|
||||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
});
|
||||
|
||||
it('should set agentless setup technology if agent policy supports agentless in edit page', async () => {
|
||||
|
@ -270,7 +557,7 @@ describe('useSetupTechnology', () => {
|
|||
expect(result.current.selectedSetupTechnology).toBe(SetupTechnology.AGENTLESS);
|
||||
});
|
||||
|
||||
it('should create agentless policy if isCloud and agentless.enabled', async () => {
|
||||
it('should create agentless policy if isCloud and agentless.enabled', async () => {
|
||||
(useConfig as MockFn).mockReturnValue({
|
||||
agentless: {
|
||||
enabled: true,
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
* 2.0.
|
||||
*/
|
||||
|
||||
import { useCallback, useMemo, useRef, useState } from 'react';
|
||||
import { useCallback, useRef, useState, useEffect } from 'react';
|
||||
|
||||
import { useConfig } from '../../../../../hooks';
|
||||
import { generateNewAgentPolicyWithDefaults } from '../../../../../../../../common/services/generate_new_agent_policy';
|
||||
|
@ -68,6 +68,7 @@ export function useSetupTechnology({
|
|||
packagePolicy,
|
||||
isEditPage,
|
||||
agentPolicies,
|
||||
integrationToEnable,
|
||||
}: {
|
||||
setNewAgentPolicy: (policy: NewAgentPolicy) => void;
|
||||
newAgentPolicy: NewAgentPolicy;
|
||||
|
@ -77,19 +78,30 @@ export function useSetupTechnology({
|
|||
packagePolicy: NewPackagePolicy;
|
||||
isEditPage?: boolean;
|
||||
agentPolicies?: AgentPolicy[];
|
||||
integrationToEnable?: string;
|
||||
}) {
|
||||
const { isAgentlessEnabled } = useAgentless();
|
||||
|
||||
// this is a placeholder for the new agent-BASED policy that will be used when the user switches from agentless to agent-based and back
|
||||
const orginalAgentPolicyRef = useRef<NewAgentPolicy>({ ...newAgentPolicy });
|
||||
const [currentAgentPolicy, setCurrentAgentPolicy] = useState(newAgentPolicy);
|
||||
const defaultSetupTechnology = useMemo(() => {
|
||||
return isOnlyAgentlessIntegration(packageInfo) || isAgentlessSetupDefault(packageInfo)
|
||||
? SetupTechnology.AGENTLESS
|
||||
: SetupTechnology.AGENT_BASED;
|
||||
}, [packageInfo]);
|
||||
const [selectedSetupTechnology, setSelectedSetupTechnology] =
|
||||
useState<SetupTechnology>(defaultSetupTechnology);
|
||||
|
||||
const [selectedSetupTechnology, setSelectedSetupTechnology] = useState<SetupTechnology>(
|
||||
SetupTechnology.AGENT_BASED
|
||||
);
|
||||
// derive default setup technology based on package info and selected integration
|
||||
const [defaultSetupTechnology, setDefaultSetupTechnology] = useState<SetupTechnology>(
|
||||
SetupTechnology.AGENT_BASED
|
||||
);
|
||||
useEffect(() => {
|
||||
const shouldBeDefault =
|
||||
isOnlyAgentlessIntegration(packageInfo, integrationToEnable) ||
|
||||
isAgentlessSetupDefault(packageInfo, integrationToEnable)
|
||||
? SetupTechnology.AGENTLESS
|
||||
: SetupTechnology.AGENT_BASED;
|
||||
setDefaultSetupTechnology(shouldBeDefault);
|
||||
setSelectedSetupTechnology(shouldBeDefault);
|
||||
}, [packageInfo, integrationToEnable]);
|
||||
|
||||
const agentlessPolicyName = getAgentlessAgentPolicyNameFromPackagePolicyName(packagePolicy.name);
|
||||
|
||||
|
@ -165,9 +177,19 @@ export function useSetupTechnology({
|
|||
};
|
||||
}
|
||||
|
||||
const isAgentlessSetupDefault = (packageInfo?: PackageInfo) => {
|
||||
// TODO: https://github.com/elastic/kibana/issues/205761
|
||||
// placeholder for the logic to determine if the agentless setup is the default
|
||||
const isAgentlessSetupDefault = (packageInfo?: PackageInfo, integrationToEnable?: string) => {
|
||||
if (
|
||||
packageInfo &&
|
||||
packageInfo.policy_templates &&
|
||||
packageInfo.policy_templates.length > 0 &&
|
||||
((integrationToEnable &&
|
||||
packageInfo?.policy_templates?.find((p) => p.name === integrationToEnable)?.deployment_modes
|
||||
?.agentless.is_default) ||
|
||||
packageInfo?.policy_templates?.every((p) => p.deployment_modes?.agentless.is_default))
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
};
|
||||
|
||||
|
|
|
@ -145,15 +145,16 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
|
||||
const [agentCount, setAgentCount] = useState<number>(0);
|
||||
|
||||
const integrationInfo = useMemo(
|
||||
() =>
|
||||
(params as AddToPolicyParams).integration
|
||||
? packageInfo?.policy_templates?.find(
|
||||
(policyTemplate) => policyTemplate.name === (params as AddToPolicyParams).integration
|
||||
)
|
||||
: undefined,
|
||||
[packageInfo?.policy_templates, params]
|
||||
const [integrationToEnable, setIntegrationToEnable] = useState<string | undefined>(
|
||||
params.integration
|
||||
);
|
||||
const integrationInfo = useMemo(() => {
|
||||
return integrationToEnable
|
||||
? packageInfo?.policy_templates?.find(
|
||||
(policyTemplate) => policyTemplate.name === integrationToEnable
|
||||
)
|
||||
: undefined;
|
||||
}, [integrationToEnable, packageInfo?.policy_templates]);
|
||||
|
||||
const showSecretsDisabledCallout =
|
||||
!fleetStatus.isSecretsStorageEnabled &&
|
||||
|
@ -187,7 +188,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
selectedPolicyTab,
|
||||
withSysMonitoring,
|
||||
queryParamsPolicyId,
|
||||
integrationToEnable: integrationInfo?.name,
|
||||
integrationToEnable,
|
||||
hasFleetAddAgentsPrivileges,
|
||||
setNewAgentPolicy,
|
||||
setSelectedPolicyTab,
|
||||
|
@ -374,6 +375,8 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
handleSetupTechnologyChange={handleSetupTechnologyChange}
|
||||
isAgentlessEnabled={isAgentlessIntegration(packageInfo)}
|
||||
defaultSetupTechnology={defaultSetupTechnology}
|
||||
integrationToEnable={integrationToEnable}
|
||||
setIntegrationToEnable={setIntegrationToEnable}
|
||||
/>
|
||||
</ExtensionWrapper>
|
||||
)
|
||||
|
@ -414,7 +417,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
{!extensionView && (
|
||||
<StepConfigurePackagePolicy
|
||||
packageInfo={packageInfo}
|
||||
showOnlyIntegration={integrationInfo?.name}
|
||||
showOnlyIntegration={integrationToEnable}
|
||||
packagePolicy={packagePolicy}
|
||||
updatePackagePolicy={updatePackagePolicy}
|
||||
validationResults={validationResults}
|
||||
|
@ -449,7 +452,7 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
extensionView,
|
||||
isAgentlessIntegration,
|
||||
selectedSetupTechnology,
|
||||
integrationInfo?.name,
|
||||
integrationToEnable,
|
||||
isAgentlessSelected,
|
||||
handleExtensionViewOnChange,
|
||||
handleSetupTechnologyChange,
|
||||
|
@ -465,18 +468,19 @@ export const CreatePackagePolicySinglePage: CreatePackagePolicyParams = ({
|
|||
children: replaceStepConfigurePackagePolicy || stepConfigurePackagePolicy,
|
||||
headingElement: 'h2',
|
||||
},
|
||||
...(selectedSetupTechnology !== SetupTechnology.AGENTLESS
|
||||
? [
|
||||
{
|
||||
title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle', {
|
||||
defaultMessage: 'Where to add this integration?',
|
||||
}),
|
||||
children: stepSelectAgentPolicy,
|
||||
headingElement: 'h2',
|
||||
},
|
||||
]
|
||||
: []),
|
||||
];
|
||||
|
||||
if (selectedSetupTechnology !== SetupTechnology.AGENTLESS) {
|
||||
steps.push({
|
||||
title: i18n.translate('xpack.fleet.createPackagePolicy.stepSelectAgentPolicyTitle', {
|
||||
defaultMessage: 'Where to add this integration?',
|
||||
}),
|
||||
children: stepSelectAgentPolicy,
|
||||
headingElement: 'h2',
|
||||
});
|
||||
}
|
||||
|
||||
// Display package error if there is one
|
||||
if (packageInfoError) {
|
||||
return (
|
||||
|
|
|
@ -46,6 +46,8 @@ export type PackagePolicyReplaceDefineStepExtensionComponentProps = (
|
|||
isAgentlessEnabled?: boolean;
|
||||
handleSetupTechnologyChange?: (setupTechnology: SetupTechnology) => void;
|
||||
defaultSetupTechnology?: SetupTechnology;
|
||||
integrationToEnable?: string;
|
||||
setIntegrationToEnable?: (integration: string) => void;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
@ -414,18 +414,6 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
// 2nd call happens on mount and increments kspm template enabled input
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
...getMockPolicyK8s(),
|
||||
inputs: policy.inputs.map((input) => ({
|
||||
...input,
|
||||
enabled: input.policy_template === 'kspm',
|
||||
})),
|
||||
name: 'kspm-1',
|
||||
},
|
||||
});
|
||||
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
|
@ -502,19 +490,6 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
// 2nd call happens on mount and increments vuln_mgmt template enabled input
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
...getMockPolicyVulnMgmtAWS(),
|
||||
inputs: policy.inputs.map((input) => ({
|
||||
...input,
|
||||
enabled: input.policy_template === 'vuln_mgmt',
|
||||
})),
|
||||
name: 'vuln_mgmt-1',
|
||||
},
|
||||
});
|
||||
|
||||
// 3rd call happens on mount and increments vuln_mgmt template enabled input
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
|
@ -589,19 +564,6 @@ describe('<CspPolicyTemplateForm />', () => {
|
|||
});
|
||||
|
||||
// 2nd call happens on mount and increments cspm template enabled input
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
...getMockPolicyAWS(),
|
||||
inputs: policy.inputs.map((input) => ({
|
||||
...input,
|
||||
enabled: input.policy_template === 'cspm',
|
||||
})),
|
||||
name: 'cspm-1',
|
||||
},
|
||||
});
|
||||
|
||||
// // 3rd call happens on mount and increments cspm template enabled input
|
||||
expect(onChange).toHaveBeenCalledWith({
|
||||
isValid: true,
|
||||
updatedPolicy: {
|
||||
|
|
|
@ -671,12 +671,16 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
|
|||
handleSetupTechnologyChange,
|
||||
isAgentlessEnabled,
|
||||
defaultSetupTechnology,
|
||||
integrationToEnable,
|
||||
setIntegrationToEnable,
|
||||
}) => {
|
||||
const integrationParam = useParams<{ integration: CloudSecurityPolicyTemplate }>().integration;
|
||||
const integration = SUPPORTED_POLICY_TEMPLATES.includes(integrationParam)
|
||||
? integrationParam
|
||||
: undefined;
|
||||
const isParentSecurityPosture = !integration;
|
||||
const integration =
|
||||
integrationToEnable &&
|
||||
SUPPORTED_POLICY_TEMPLATES.includes(integrationToEnable as CloudSecurityPolicyTemplate)
|
||||
? integrationToEnable
|
||||
: undefined;
|
||||
const isParentSecurityPosture = !integrationParam;
|
||||
// Handling validation state
|
||||
const [isValid, setIsValid] = useState(true);
|
||||
const { cloud } = useKibana().services;
|
||||
|
@ -803,18 +807,6 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
|
|||
// Required for mount only to ensure a single input type is selected
|
||||
// This will remove errors in validationResults.vars
|
||||
setEnabledPolicyInput(DEFAULT_INPUT_TYPE[input.policy_template]);
|
||||
|
||||
// When the integration is the parent Security Posture (!integration) we need to
|
||||
// reset the setup technology when the integration option changes if it was set to agentless for CSPM
|
||||
if (isParentSecurityPosture && input.policy_template !== 'cspm') {
|
||||
updateSetupTechnology(SetupTechnology.AGENT_BASED);
|
||||
} else if (
|
||||
isParentSecurityPosture &&
|
||||
input.policy_template === 'cspm' &&
|
||||
defaultSetupTechnology
|
||||
) {
|
||||
updateSetupTechnology(defaultSetupTechnology);
|
||||
}
|
||||
refetch();
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [isLoading, input.policy_template, isEditPage]);
|
||||
|
@ -825,6 +817,7 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
|
|||
}
|
||||
|
||||
setEnabledPolicyInput(input.type);
|
||||
setIntegrationToEnable?.(input.policy_template);
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [setupTechnology]);
|
||||
|
||||
|
@ -840,7 +833,7 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
|
|||
packagePolicyList: packagePolicyList?.items,
|
||||
isEditPage,
|
||||
isLoading,
|
||||
integration,
|
||||
integration: integration as CloudSecurityPolicyTemplate,
|
||||
newPolicy,
|
||||
updatePolicy,
|
||||
setCanFetchIntegration,
|
||||
|
@ -889,12 +882,15 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio
|
|||
<>
|
||||
{isEditPage && <EditScreenStepTitle />}
|
||||
{/* Defines the enabled policy template */}
|
||||
{!integration && (
|
||||
{isParentSecurityPosture && (
|
||||
<>
|
||||
<PolicyTemplateSelector
|
||||
selectedTemplate={input.policy_template}
|
||||
policy={newPolicy}
|
||||
setPolicyTemplate={(template) => setEnabledPolicyInput(DEFAULT_INPUT_TYPE[template])}
|
||||
setPolicyTemplate={(template) => {
|
||||
setEnabledPolicyInput(DEFAULT_INPUT_TYPE[template]);
|
||||
setIntegrationToEnable?.(template);
|
||||
}}
|
||||
disabled={isEditPage}
|
||||
/>
|
||||
<EuiSpacer size="l" />
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
* 2.0; you may not use this file except in compliance with the Elastic License
|
||||
* 2.0.
|
||||
*/
|
||||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
|
||||
import { NewPackagePolicyInput } from '@kbn/fleet-plugin/common';
|
||||
import { SetupTechnology } from '@kbn/fleet-plugin/public';
|
||||
|
@ -35,6 +35,12 @@ export const useSetupTechnology = ({
|
|||
defaultSetupTechnology || defaultEditSetupTechnology
|
||||
);
|
||||
|
||||
// Default setup technology may update asynchrounously as data loads from
|
||||
// parent component, or when integration is changed, so re-set state if it changes
|
||||
useEffect(() => {
|
||||
setSetupTechnology(defaultSetupTechnology || defaultEditSetupTechnology);
|
||||
}, [defaultEditSetupTechnology, defaultSetupTechnology]);
|
||||
|
||||
const updateSetupTechnology = (value: SetupTechnology) => {
|
||||
setSetupTechnology(value);
|
||||
if (handleSetupTechnologyChange) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue