Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
811827c
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 10, 2023
076d6d8
WIP: Cloud Formation
opauloh Apr 11, 2023
54b7a07
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 12, 2023
d1aabec
wip: cloud formation instructions
opauloh Apr 12, 2023
3fdd5a1
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 12, 2023
e82be93
adding vuln mgmt mocks
opauloh Apr 17, 2023
fc2c9c4
add vuln mgmt cloud formation utils
opauloh Apr 17, 2023
30825a8
add use cloud formation hook to policy template form
opauloh Apr 17, 2023
735c026
add test for vuln mgmt
opauloh Apr 17, 2023
22be93f
add cloud formation types
opauloh Apr 17, 2023
4369ef6
Add CloudFormation in agent policy
opauloh Apr 17, 2023
cddaea8
add CloudFormation to agent management
opauloh Apr 17, 2023
735f504
add method to update AgentPolicy on integration
opauloh Apr 17, 2023
78bf72d
update AgentPolicy saved object
opauloh Apr 17, 2023
605ef26
update AgentPolicy Schema
opauloh Apr 17, 2023
37f18f9
Refactor: allow cloud formation to be more generic
opauloh Apr 17, 2023
06a9956
refactor: allow cloud formation to be more generic
opauloh Apr 17, 2023
912efc6
CloudFormation agent enrolment instructions
opauloh Apr 17, 2023
52800fb
update text
opauloh Apr 17, 2023
86fcf50
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 17, 2023
bf35e7c
fix optional types
opauloh Apr 17, 2023
9630054
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 17, 2023
c1410aa
fixing types
opauloh Apr 17, 2023
4a436d0
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 17, 2023
dd94c44
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 17, 2023
4de5983
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 20, 2023
0386176
reverting cloudformation from advanced agent policy
opauloh Apr 20, 2023
cb9a90a
update snapshot
opauloh Apr 20, 2023
0d3e737
remove unnecessary mapping
opauloh Apr 20, 2023
f5f1e13
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 21, 2023
9ae0bd9
reverting ui extension updatepackagepolicy
opauloh Apr 21, 2023
12c1127
set cloud formation to config inputs
opauloh Apr 21, 2023
ac33961
removing cloudFormation from AgentPolicy schema
opauloh Apr 21, 2023
bd353e0
add get cloud formation from package policy
opauloh Apr 21, 2023
6192603
change cloudFormation to cloudFormationTemplateUrl
opauloh Apr 21, 2023
a833b7e
refactor cloudFormation instructions
opauloh Apr 21, 2023
98d9761
updating tests
opauloh Apr 21, 2023
cce4d41
addressing pr suggestions
opauloh Apr 21, 2023
2cd1d7d
addressing pr comments
opauloh Apr 21, 2023
74e39f0
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 25, 2023
5993ebc
removing unneeded useEffect and useState
opauloh Apr 25, 2023
3a37f4f
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 25, 2023
732e87b
Merge branch 'main' into vuln/add-cloudformation-deploy-method
opauloh Apr 26, 2023
File filter

Filter by extension

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 @@ -5,19 +5,50 @@
* 2.0.
*/
import type { NewPackagePolicy } from '@kbn/fleet-plugin/public';
import type { PackageInfo } from '@kbn/fleet-plugin/common';
import { createNewPackagePolicyMock } from '@kbn/fleet-plugin/common/mocks';
import {
CLOUDBEAT_GCP,
CLOUDBEAT_AZURE,
CLOUDBEAT_EKS,
CLOUDBEAT_VANILLA,
CLOUDBEAT_AWS,
CLOUDBEAT_VULN_MGMT_AWS,
} from '../../../common/constants';
import type { PostureInput } from '../../../common/types';

export const getMockPolicyAWS = () => getPolicyMock(CLOUDBEAT_AWS, 'cspm', 'aws');
export const getMockPolicyK8s = () => getPolicyMock(CLOUDBEAT_VANILLA, 'kspm', 'self_managed');
export const getMockPolicyEKS = () => getPolicyMock(CLOUDBEAT_EKS, 'kspm', 'eks');
export const getMockPolicyVulnMgmtAWS = () =>
getPolicyMock(CLOUDBEAT_VULN_MGMT_AWS, 'vuln_mgmt', 'aws');

export const getMockPackageInfoVulnMgmtAWS = () => {
return {
policy_templates: [
{
title: '',
description: '',
name: 'vuln_mgmt',
inputs: [
{
type: 'cloudbeat/vuln_mgmt_aws',
title: '',
description: '',
vars: [
{
type: 'text',
name: 'cloud_formation_template',
default: 's3_url',
show_user: false,
},
],
},
],
},
],
} as PackageInfo;
};

const getPolicyMock = (
type: PostureInput,
Expand Down Expand Up @@ -84,6 +115,12 @@ const getPolicyMock = (
enabled: false,
streams: [{ enabled: false, data_stream: dataStream }],
},
{
type: CLOUDBEAT_VULN_MGMT_AWS,
policy_template: 'vuln_mgmt',
enabled: type === CLOUDBEAT_VULN_MGMT_AWS,
streams: [{ enabled: false, data_stream: dataStream }],
},
],
};
};
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,19 @@ import React from 'react';
import { render } from '@testing-library/react';
import { CspPolicyTemplateForm } from './policy_template_form';
import { TestProvider } from '../../test/test_provider';
import { getMockPolicyAWS, getMockPolicyEKS, getMockPolicyK8s } from './mocks';
import type { NewPackagePolicy, PackageInfo, PackagePolicy } from '@kbn/fleet-plugin/common';
import {
getMockPackageInfoVulnMgmtAWS,
getMockPolicyAWS,
getMockPolicyEKS,
getMockPolicyK8s,
getMockPolicyVulnMgmtAWS,
} from './mocks';
import type {
AgentPolicy,
NewPackagePolicy,
PackageInfo,
PackagePolicy,
} from '@kbn/fleet-plugin/common';
import userEvent from '@testing-library/user-event';
import { getPosturePolicy } from './utils';
import { CLOUDBEAT_AWS, CLOUDBEAT_EKS } from '../../../common/constants';
Expand All @@ -26,11 +37,14 @@ jest.mock('react-router-dom', () => ({
}));
jest.mock('../../common/api/use_setup_status_api');

const onChange = jest.fn();

describe('<CspPolicyTemplateForm />', () => {
beforeEach(() => {
(useParams as jest.Mock).mockReturnValue({
integration: undefined,
});
onChange.mockClear();
(useCspSetupStatusApi as jest.Mock).mockImplementation(() =>
createReactQueryResponse({
status: 'success',
Expand All @@ -39,40 +53,40 @@ describe('<CspPolicyTemplateForm />', () => {
);
});

const onChange = jest.fn();

const WrappedComponent = ({
newPolicy,
edit = false,
agentPolicy,
packageInfo = {} as PackageInfo,
}: {
edit?: boolean;
newPolicy: NewPackagePolicy;
agentPolicy?: AgentPolicy;
packageInfo?: PackageInfo;
}) => (
<TestProvider>
{edit && (
<CspPolicyTemplateForm
policy={newPolicy as PackagePolicy}
newPolicy={newPolicy}
onChange={onChange}
packageInfo={{} as PackageInfo}
packageInfo={packageInfo}
isEditPage={true}
agentPolicy={agentPolicy}
/>
)}
{!edit && (
<CspPolicyTemplateForm
newPolicy={newPolicy}
onChange={onChange}
packageInfo={{} as PackageInfo}
packageInfo={packageInfo}
isEditPage={false}
agentPolicy={agentPolicy}
/>
)}
</TestProvider>
);

beforeEach(() => {
onChange.mockClear();
});

it('updates package policy namespace to default when it changes', () => {
const policy = getMockPolicyK8s();
const { rerender } = render(<WrappedComponent newPolicy={policy} />);
Expand Down Expand Up @@ -505,4 +519,31 @@ describe('<CspPolicyTemplateForm />', () => {
});
});
}

describe('Vuln Mgmt', () => {
it('Update Agent Policy CloudFormation template from vars', () => {
const policy = getMockPolicyVulnMgmtAWS();

const packageInfo = getMockPackageInfoVulnMgmtAWS();
render(<WrappedComponent newPolicy={policy} packageInfo={packageInfo} />);

const expectedUpdatedPolicy = {
...policy,
inputs: policy.inputs.map((input) => {
if (input.type === 'cloudbeat/vuln_mgmt_aws') {
return {
...input,
config: { cloud_formation_template_url: { value: 's3_url' } },
};
}
return input;
}),
};

expect(onChange).toHaveBeenNthCalledWith(2, {
isValid: true,
updatedPolicy: expectedUpdatedPolicy,
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import type {
NewPackagePolicyInput,
PackagePolicyReplaceDefineStepExtensionComponentProps,
} from '@kbn/fleet-plugin/public/types';
import type { PackageInfo } from '@kbn/fleet-plugin/common';
import { useParams } from 'react-router-dom';
import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types';
import {
Expand All @@ -32,6 +33,7 @@ import {
import {
getPosturePolicy,
getPostureInputHiddenVars,
getVulnMgmtCloudFormationDefaultValue,
POSTURE_NAMESPACE,
type NewPackagePolicyPostureInput,
isPostureInput,
Expand Down Expand Up @@ -86,11 +88,12 @@ const IntegrationSettings = ({ onChange, fields }: IntegrationInfoFieldsProps) =
);

export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensionComponentProps>(
({ newPolicy, onChange, validationResults, isEditPage }) => {
({ newPolicy, onChange, validationResults, isEditPage, packageInfo }) => {
const integrationParam = useParams<{ integration: CloudSecurityPolicyTemplate }>().integration;
const integration = SUPPORTED_POLICY_TEMPLATES.includes(integrationParam)
? integrationParam
: undefined;

const input = getSelectedOption(newPolicy.inputs, integration);

const updatePolicy = useCallback(
Expand Down Expand Up @@ -150,6 +153,12 @@ export const CspPolicyTemplateForm = memo<PackagePolicyReplaceDefineStepExtensio

useEnsureDefaultNamespace({ newPolicy, input, updatePolicy });

useCloudFormationTemplate({
packageInfo,
updatePolicy,
newPolicy,
});

if (isLoading) {
return (
<EuiFlexGroup justifyContent="spaceAround">
Expand Down Expand Up @@ -301,3 +310,45 @@ const getSelectedOption = (

return selectedOption;
};

/**
* Update CloudFormation template and stack name in the Agent Policy
* based on the selected policy template
*/
const useCloudFormationTemplate = ({
packageInfo,
newPolicy,
updatePolicy,
}: {
packageInfo: PackageInfo;
newPolicy: NewPackagePolicy;
updatePolicy: (policy: NewPackagePolicy) => void;
}) => {
useEffect(() => {
const templateUrl = getVulnMgmtCloudFormationDefaultValue(packageInfo);

// If the template is not available, do not update the policy
if (templateUrl === '') return;

const checkCurrentTemplate = newPolicy?.inputs?.find(
(i: any) => i.type === CLOUDBEAT_VULN_MGMT_AWS
)?.config?.cloud_formation_template_url?.value;

// If the template is already set, do not update the policy
if (checkCurrentTemplate === templateUrl) return;

updatePolicy?.({
...newPolicy,
inputs: newPolicy.inputs.map((input) => {
if (input.type === CLOUDBEAT_VULN_MGMT_AWS) {
return {
...input,
config: { cloud_formation_template_url: { value: templateUrl } },
};
}
return input;
}),
});
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [newPolicy?.vars?.cloud_formation_template_url, newPolicy, packageInfo]);
};
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
import type {
NewPackagePolicy,
NewPackagePolicyInput,
PackageInfo,
PackagePolicyConfigRecordEntry,
RegistryPolicyTemplate,
RegistryVarsEntry,
} from '@kbn/fleet-plugin/common';
import merge from 'lodash/merge';
import {
Expand All @@ -21,6 +24,7 @@ import {
SUPPORTED_CLOUDBEAT_INPUTS,
CSPM_POLICY_TEMPLATE,
KSPM_POLICY_TEMPLATE,
VULN_MGMT_POLICY_TEMPLATE,
} from '../../../common/constants';
import { DEFAULT_AWS_VARS_GROUP } from './aws_credentials_form';
import type { PostureInput, CloudSecurityPolicyTemplate } from '../../../common/types';
Expand All @@ -34,7 +38,8 @@ type PosturePolicyInput =
| { type: typeof CLOUDBEAT_GCP; policy_template: typeof CSPM_POLICY_TEMPLATE }
| { type: typeof CLOUDBEAT_AWS; policy_template: typeof CSPM_POLICY_TEMPLATE }
| { type: typeof CLOUDBEAT_VANILLA; policy_template: typeof KSPM_POLICY_TEMPLATE }
| { type: typeof CLOUDBEAT_EKS; policy_template: typeof KSPM_POLICY_TEMPLATE };
| { type: typeof CLOUDBEAT_EKS; policy_template: typeof KSPM_POLICY_TEMPLATE }
| { type: typeof CLOUDBEAT_VULN_MGMT_AWS; policy_template: typeof VULN_MGMT_POLICY_TEMPLATE };

// Extend NewPackagePolicyInput with known string literals for input type and policy template
export type NewPackagePolicyPostureInput = NewPackagePolicyInput & PosturePolicyInput;
Expand Down Expand Up @@ -121,6 +126,40 @@ export const getPosturePolicy = (
}),
});

type RegistryPolicyTemplateWithInputs = RegistryPolicyTemplate & {
inputs: Array<{
vars?: RegistryVarsEntry[];
}>;
};
// type guard for checking inputs
export const hasPolicyTemplateInputs = (
policyTemplate: RegistryPolicyTemplate
): policyTemplate is RegistryPolicyTemplateWithInputs => {
return policyTemplate.hasOwnProperty('inputs');
};

export const getVulnMgmtCloudFormationDefaultValue = (packageInfo: PackageInfo): string => {
if (!packageInfo.policy_templates) return '';

const vulnMgmtPolicyTemplate = packageInfo.policy_templates.find(
(p) => p.name === VULN_MGMT_POLICY_TEMPLATE
);
if (!vulnMgmtPolicyTemplate) return '';

const vulnMgmtInputs =
hasPolicyTemplateInputs(vulnMgmtPolicyTemplate) && vulnMgmtPolicyTemplate.inputs;

if (!vulnMgmtInputs) return '';

const cloudFormationTemplate = vulnMgmtInputs.reduce((acc, input): string => {
if (!input.vars) return acc;
const template = input.vars.find((v) => v.name === 'cloud_formation_template')?.default;
return template ? String(template) : acc;
}, '');

return cloudFormationTemplate;
};

/**
* Input vars that are hidden from the user
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ function getArtifact(platform: PLATFORM_TYPE, kibanaVersion: string) {
kubernetes: {
downloadCommand: '',
},
cloudFormation: {
downloadCommand: '',
},
};

return artifactMap[platform];
Expand Down Expand Up @@ -115,6 +118,7 @@ export function getInstallCommandForPlatform(
deb: `${artifact.downloadCommand}\nsudo elastic-agent enroll ${commandArgumentsStr}\nsudo systemctl enable elastic-agent\nsudo systemctl start elastic-agent`,
rpm: `${artifact.downloadCommand}\nsudo elastic-agent enroll ${commandArgumentsStr}\nsudo systemctl enable elastic-agent\nsudo systemctl start elastic-agent`,
kubernetes: '',
cloudFormation: '',
};

return commands[platform];
Expand Down
Loading