Skip to content

Commit

Permalink
[D4C] updated cloud_defend to use new fleet extension (#157342)
Browse files Browse the repository at this point in the history
## Summary

Fixes an onboarding issue related to using the old "create" and "edit"
fleet extensions. Agent flyout would not automatically open after adding
the integration.

Using the 'package-policy-replace-define-step' hook fixes the problem.

New hook does not implement integration **name** and **description**
fields, so those were added in as well.


![image](https://github.com/elastic/kibana/assets/16198204/f046ebfc-71df-4293-ac87-6589e3f13ef7)

### Checklist

Delete any items that are not applicable to this PR.

- [x] Any text added follows [EUI's writing
guidelines](https://elastic.github.io/eui/#/guidelines/writing), uses
sentence case text and includes [i18n
support](https://github.com/elastic/kibana/blob/main/packages/kbn-i18n/README.md)
- [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
mitodrummer authored May 11, 2023
1 parent a520001 commit f884e24
Show file tree
Hide file tree
Showing 8 changed files with 150 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
/*
* 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 React, { memo } from 'react';
import type { PackagePolicyReplaceDefineStepExtensionComponentProps } from '@kbn/fleet-plugin/public/types';
import { PolicySettings } from '../policy_settings';

export const CloudDefendFleetPolicyReplaceDefineStepExtension =
memo<PackagePolicyReplaceDefineStepExtensionComponentProps>(
({ newPolicy, onChange }: PackagePolicyReplaceDefineStepExtensionComponentProps) => {
const policy = JSON.parse(JSON.stringify(newPolicy));

return <PolicySettings policy={policy} onChange={onChange} />;
}
);

CloudDefendFleetPolicyReplaceDefineStepExtension.displayName =
'CloudDefendFleetPolicyReplaceDefineStepExtension';

// eslint-disable-next-line import/no-default-export
export { CloudDefendFleetPolicyReplaceDefineStepExtension as default };

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,36 @@ describe('<PolicySettings />', () => {
onChange.mockClear();
});

it('allows user to set name of integration', () => {
const { getByTestId } = render(<WrappedComponent />);
const input = getByTestId('cloud-defend-policy-name');

if (input) {
userEvent.type(input, '1');
} else {
throw new Error("Can't find input");
}

const { updatedPolicy } = onChange.mock.calls[0][0];

expect(updatedPolicy.name).toEqual('some-cloud_defend-policy1');
});

it('allows user to set description of integration', () => {
const { getByTestId } = render(<WrappedComponent />);
const input = getByTestId('cloud-defend-policy-description');

if (input) {
userEvent.type(input, '1');
} else {
throw new Error("Can't find input");
}

const { updatedPolicy } = onChange.mock.calls[0][0];

expect(updatedPolicy.description).toEqual('1');
});

it('renders a checkbox to toggle BPF/LSM control mechanism', () => {
const { getByTestId } = render(<WrappedComponent />);
const input = getByTestId('cloud-defend-controltoggle');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,49 +4,111 @@
* 2.0; you may not use this file except in compliance with the Elastic License
* 2.0.
*/
import React, { useCallback, useMemo } from 'react';
import { EuiSwitch, EuiSpacer, EuiText, EuiFlexGroup, EuiFlexItem } from '@elastic/eui';
import React, { useCallback, FormEvent, useState } from 'react';
import {
EuiTextArea,
EuiSwitch,
EuiSpacer,
EuiText,
EuiFlexGroup,
EuiFlexItem,
EuiForm,
EuiFormRow,
EuiFieldText,
EuiHorizontalRule,
} from '@elastic/eui';
import { INPUT_CONTROL } from '../../../common/constants';
import { getInputFromPolicy } from '../../common/utils';
import * as i18n from './translations';
import { ControlSettings } from '../control_settings';
import type { SettingsDeps } from '../../types';
import { SettingsDeps, OnChangeDeps } from '../../types';

export const PolicySettings = ({ policy, onChange }: SettingsDeps) => {
const [policyHasErrors, setPolicyHasErrors] = useState(false);
const controlInput = getInputFromPolicy(policy, INPUT_CONTROL);
const controlEnabled = !!controlInput?.enabled;
const policyCopy = useMemo(() => JSON.parse(JSON.stringify(policy)), [policy]);

const onToggleEnabled = useCallback(
(e) => {
if (controlInput) {
controlInput.enabled = e.target.checked;

onChange({ isValid: true, updatedPolicy: policy });
onChange({ isValid: !policyHasErrors, updatedPolicy: { ...policy } });
}
},
[controlInput, onChange, policy]
[controlInput, onChange, policyHasErrors, policy]
);

const onNameChange = useCallback(
(event: FormEvent<HTMLInputElement>) => {
const name = event.currentTarget.value;

onChange({ isValid: !policyHasErrors, updatedPolicy: { ...policy, name } });
},
[onChange, policyHasErrors, policy]
);

const onDescriptionChange = useCallback(
(event: FormEvent<HTMLTextAreaElement>) => {
const description = event.currentTarget.value;

onChange({ isValid: !policyHasErrors, updatedPolicy: { ...policy, description } });
},
[onChange, policyHasErrors, policy]
);

const onPolicyChange = useCallback(
(props: OnChangeDeps) => {
setPolicyHasErrors(!props.isValid);
onChange(props);
},
[onChange]
);

return (
<EuiFlexGroup direction="column">
<EuiFlexItem>
<EuiSwitch
data-test-subj="cloud-defend-controltoggle"
label={i18n.enableControl}
checked={controlEnabled}
onChange={onToggleEnabled}
/>
<EuiSpacer size="s" />
<EuiText color="subdued" size="s">
{i18n.enableControlHelp}
</EuiText>
<EuiForm component="form">
<EuiFormRow label={i18n.name} fullWidth={true}>
<EuiFieldText
fullWidth={true}
name="name"
value={policy.name}
onChange={onNameChange}
data-test-subj="cloud-defend-policy-name"
/>
</EuiFormRow>
<EuiFormRow label={i18n.description} fullWidth={true}>
<EuiTextArea
fullWidth={true}
name="name"
value={policy.description}
onChange={onDescriptionChange}
data-test-subj="cloud-defend-policy-description"
compressed
/>
</EuiFormRow>
<EuiHorizontalRule />
<EuiFormRow fullWidth>
<EuiFlexItem>
<EuiSwitch
data-test-subj="cloud-defend-controltoggle"
label={i18n.enableControl}
checked={controlEnabled}
onChange={onToggleEnabled}
/>
<EuiSpacer size="s" />
<EuiText color="subdued" size="s">
{i18n.enableControlHelp}
</EuiText>
</EuiFlexItem>
</EuiFormRow>
</EuiForm>
</EuiFlexItem>
{controlEnabled && (
<ControlSettings
data-test-subj="cloud-defend-controlsettings"
policy={policyCopy}
onChange={onChange}
policy={policy}
onChange={onPolicyChange}
/>
)}
</EuiFlexGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,18 @@

import { i18n } from '@kbn/i18n';

export const name = i18n.translate('xpack.cloudDefend.name', {
defaultMessage: 'Name',
});

export const description = i18n.translate('xpack.cloudDefend.description', {
defaultMessage: 'Description',
});

export const enableControl = i18n.translate('xpack.cloudDefend.enableControl', {
defaultMessage: 'Enable drift prevention',
defaultMessage: 'Enable policy',
});

export const enableControlHelp = i18n.translate('xpack.cloudDefend.enableControlHelp', {
defaultMessage:
'Toggles enablement of drift prevention policy to alert and/or block file operations.',
defaultMessage: 'Enables drift prevention, alert, and logging policy shown below.',
});
15 changes: 4 additions & 11 deletions x-pack/plugins/cloud_defend/public/plugin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ import { INTEGRATION_PACKAGE_NAME } from '../common/constants';
import { LoadingState } from './components/loading_state';
import { SetupContext } from './application/setup_context';

const LazyEditPolicy = lazy(() => import('./components/fleet_extensions/policy_extension_edit'));
const LazyCreatePolicy = lazy(
() => import('./components/fleet_extensions/policy_extension_create')
const LazyPolicyReplaceDefineStepExtension = lazy(
() => import('./components/fleet_extensions/package_policy_replace_define_step_extension')
);

const RouterLazy = lazy(() => import('./application/router'));
Expand Down Expand Up @@ -55,14 +54,8 @@ export class CloudDefendPlugin
public start(core: CoreStart, plugins: CloudDefendPluginStartDeps): CloudDefendPluginStart {
plugins.fleet.registerExtension({
package: INTEGRATION_PACKAGE_NAME,
view: 'package-policy-create',
Component: LazyCreatePolicy,
});

plugins.fleet.registerExtension({
package: INTEGRATION_PACKAGE_NAME,
view: 'package-policy-edit',
Component: LazyEditPolicy,
view: 'package-policy-replace-define-step',
Component: LazyPolicyReplaceDefineStepExtension,
});

const CloudDefendRouter = (props: CloudDefendRouterProps) => (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { PLUGIN_ID, INTEGRATIONS_PLUGIN_ID, pagePathGetters } from '../../../../
const EXCLUDED_PACKAGES = [
'apm',
'cloud_security_posture',
'cloud_defend',
'dga',
'fleet_server',
'osquery_manager',
Expand Down

0 comments on commit f884e24

Please sign in to comment.