From e243f6e42291b7d9165d7264272a0fd2949b3661 Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Mon, 22 Aug 2022 09:29:41 -0700 Subject: [PATCH 01/28] draft for onboarding new UI --- .../endpoint_policy_create_extension.tsx | 168 ++++++++++++++++-- 1 file changed, 157 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index ece9464d0c34d..d4fed4a1f0acb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -5,8 +5,8 @@ * 2.0. */ -import React, { memo, useEffect } from 'react'; -import { EuiCallOut, EuiSpacer, EuiText } from '@elastic/eui'; +import React, { memo, useState, useCallback, useEffect } from 'react'; +import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; @@ -19,6 +19,7 @@ export const EndpointPolicyCreateExtension = memo { onChange({ isValid: false, @@ -29,22 +30,167 @@ export const EndpointPolicyCreateExtension = memo { + setDropdownValue(e?.target?.value); + } + + const [radioInteractiveSelected, setRadioInteractiveSelected] = useState(true); + const [radioComprehensiveSelected, setRadioComprehensiveSelected] = useState(false); + + + const onChangeRadio = () => { + setRadioInteractiveSelected(!radioInteractiveSelected); + setRadioComprehensiveSelected(!radioComprehensiveSelected); + } +/// Endpoint Radio Options (NGAV and EDRs) + const [radioEndpointOption, setRadioEndpointOption] = useState('NGAV') + + const onChangeRadioEndpoint = useCallback ((e) => { + setRadioEndpointOption(e.target.value) + if(e.target.value === 'NGAV'){ + // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs: newPolicy.inputs.concat([{ config : { _create : {policyParams : {value_test: 'NGAV', sessionData: false}}}}])}}) + onChange({isValid:true, updatedPolicy : {...newPolicy}}) + } + else if(e.target.value === 'EDR Essential'){ + // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Essential', sessionData: false}}}}]}}) + onChange({isValid:true, updatedPolicy : {...newPolicy}}) + } + else if(e.target.value === 'EDR Complete'){ + onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Complete', sessionData: true}}}}]}}) + } + },[]) +/// + + const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(true); + const [checkboxRansomwareChecked, setCheckboxRansomwareChecked] = useState(true); + + const onChangeMalwareCheckbox = useCallback( () => { + setCheckboxMalwareChecked(!checkboxMalwareChecked) + onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) + },[checkboxMalwareChecked, newPolicy] ) + + const onChangeRansomwareCheckbox = useCallback(() => { + setCheckboxRansomwareChecked(!checkboxRansomwareChecked) + onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) + },[checkboxRansomwareChecked, newPolicy] ) return ( + +
Use quick settings to configure the integration to protect your tranditional endpoints or dynamic clound environments. You can make changes to the configurations after you add it.
+ onChangeDropdown(e)} + fullWidth={true} + /> + + {dropdownValue === dropDownOptions[0].value && ( <> - - - -

+

Enable prevention
+
In addition to detections, Elastic security can prevent threat before they happen. You can disable detections later in the agent policy configurations settings.
+ + onChangeRadioEndpoint(e)} + /> + + + onChangeRadioEndpoint(e)} + /> + + + onChangeRadioEndpoint(e)} + /> + + + )} + + {dropdownValue === dropDownOptions[1].value && ( + <> +
Monitoring mode
+ + + + + + -

-
-
+ + + +
Enable Prevention
+
In addition to detections, Elastic security can prevent threats before they happen. You can disable detections anytime in the agent policy configurations settings.
+ + + + + + + + + )} +
); } ); EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; + From c0baf23c6e8f9c5afafeeb3cadfd0d1dff2feb7b Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Mon, 22 Aug 2022 17:58:40 +0000 Subject: [PATCH 02/28] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../endpoint_policy_create_extension.tsx | 324 +++++++++++------- 1 file changed, 192 insertions(+), 132 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index d4fed4a1f0acb..082c677fda2dc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -6,7 +6,7 @@ */ import React, { memo, useState, useCallback, useEffect } from 'react'; -import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; +import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; @@ -30,167 +30,227 @@ export const EndpointPolicyCreateExtension = memo { + const onChangeDropdown = (e: string) => { setDropdownValue(e?.target?.value); - } + }; const [radioInteractiveSelected, setRadioInteractiveSelected] = useState(true); const [radioComprehensiveSelected, setRadioComprehensiveSelected] = useState(false); - const onChangeRadio = () => { - setRadioInteractiveSelected(!radioInteractiveSelected); - setRadioComprehensiveSelected(!radioComprehensiveSelected); - } -/// Endpoint Radio Options (NGAV and EDRs) - const [radioEndpointOption, setRadioEndpointOption] = useState('NGAV') - - const onChangeRadioEndpoint = useCallback ((e) => { - setRadioEndpointOption(e.target.value) - if(e.target.value === 'NGAV'){ - // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs: newPolicy.inputs.concat([{ config : { _create : {policyParams : {value_test: 'NGAV', sessionData: false}}}}])}}) - onChange({isValid:true, updatedPolicy : {...newPolicy}}) - } - else if(e.target.value === 'EDR Essential'){ - // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Essential', sessionData: false}}}}]}}) - onChange({isValid:true, updatedPolicy : {...newPolicy}}) - } - else if(e.target.value === 'EDR Complete'){ - onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Complete', sessionData: true}}}}]}}) + setRadioInteractiveSelected(!radioInteractiveSelected); + setRadioComprehensiveSelected(!radioComprehensiveSelected); + }; + // / Endpoint Radio Options (NGAV and EDRs) + const [radioEndpointOption, setRadioEndpointOption] = useState('NGAV'); + + const onChangeRadioEndpoint = useCallback((e) => { + setRadioEndpointOption(e.target.value); + if (e.target.value === 'NGAV') { + // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs: newPolicy.inputs.concat([{ config : { _create : {policyParams : {value_test: 'NGAV', sessionData: false}}}}])}}) + onChange({ isValid: true, updatedPolicy: { ...newPolicy } }); + } else if (e.target.value === 'EDR Essential') { + // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Essential', sessionData: false}}}}]}}) + onChange({ isValid: true, updatedPolicy: { ...newPolicy } }); + } else if (e.target.value === 'EDR Complete') { + onChange({ + isValid: true, + updatedPolicy: { + ...newPolicy, + inputs: [ + { + config: { + _create: { policyParams: { value_test: 'EDR Complete', sessionData: true } }, + }, + }, + ], + }, + }); } - },[]) -/// + }, []); + /// const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(true); const [checkboxRansomwareChecked, setCheckboxRansomwareChecked] = useState(true); - const onChangeMalwareCheckbox = useCallback( () => { - setCheckboxMalwareChecked(!checkboxMalwareChecked) - onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) - },[checkboxMalwareChecked, newPolicy] ) + const onChangeMalwareCheckbox = useCallback(() => { + setCheckboxMalwareChecked(!checkboxMalwareChecked); + onChange({ + isValid: 'VALID', + updatedPolicy: { + packagePolicyOnboardingParam: { + sessionData: true, + protections: { + ransomware: !checkboxRansomwareChecked, + malware: !checkboxMalwareChecked, + }, + }, + }, + }); + }, [checkboxMalwareChecked, newPolicy]); - const onChangeRansomwareCheckbox = useCallback(() => { - setCheckboxRansomwareChecked(!checkboxRansomwareChecked) - onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) - },[checkboxRansomwareChecked, newPolicy] ) + const onChangeRansomwareCheckbox = useCallback(() => { + setCheckboxRansomwareChecked(!checkboxRansomwareChecked); + onChange({ + isValid: 'VALID', + updatedPolicy: { + packagePolicyOnboardingParam: { + sessionData: true, + protections: { + ransomware: !checkboxRansomwareChecked, + malware: !checkboxMalwareChecked, + }, + }, + }, + }); + }, [checkboxRansomwareChecked, newPolicy]); return ( -
Use quick settings to configure the integration to protect your tranditional endpoints or dynamic clound environments. You can make changes to the configurations after you add it.
- onChangeDropdown(e)} - fullWidth={true} - /> - - {dropdownValue === dropDownOptions[0].value && ( - <> -
Enable prevention
-
In addition to detections, Elastic security can prevent threat before they happen. You can disable detections later in the agent policy configurations settings.
- - + Use quick settings to configure the integration to protect your tranditional endpoints or + dynamic clound environments. You can make changes to the configurations after you add it. + + onChangeDropdown(e)} + fullWidth={true} + /> + + {dropdownValue === dropDownOptions[0].value && ( + <> +
+ Enable prevention +
+
+ In addition to detections, Elastic security can prevent threat before they happen. You + can disable detections later in the agent policy configurations settings. +
+ + onChangeRadioEndpoint(e)} - /> - - - onChangeRadioEndpoint(e)} + /> + + + onChangeRadioEndpoint(e)} - /> - - - onChangeRadioEndpoint(e)} + /> + + + onChangeRadioEndpoint(e)} - /> - - - )} - - {dropdownValue === dropDownOptions[1].value && ( - <> -
Monitoring mode
- - - - - - - - - - -
Enable Prevention
-
In addition to detections, Elastic security can prevent threats before they happen. You can disable detections anytime in the agent policy configurations settings.
- - - - - - - - - - )} -
+ checked={radioEndpointOption === 'EDR Complete'} + onChange={(e) => onChangeRadioEndpoint(e)} + /> + + + )} + + {dropdownValue === dropDownOptions[1].value && ( + <> +
+ Monitoring mode +
+ + + + + + + +
+ Enable Prevention +
+
+ In addition to detections, Elastic security can prevent threats before they happen. + You can disable detections anytime in the agent policy configurations settings. +
+ + + + + + + + + + )} + ); } ); EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; - From b29de627f5be54534c408a71aae4d8b233b23c04 Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Mon, 22 Aug 2022 16:11:27 -0700 Subject: [PATCH 03/28] added payload formation + simple UI, TODO: polish UI --- .../endpoint_policy_create_extension.tsx | 496 +++++++++++++----- 1 file changed, 365 insertions(+), 131 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index d4fed4a1f0acb..4858d6c10b165 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -6,7 +6,7 @@ */ import React, { memo, useState, useCallback, useEffect } from 'react'; -import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; +import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; @@ -20,177 +20,411 @@ export const EndpointPolicyCreateExtension = memo { onChange({ isValid: false, updatedPolicy: { ...newPolicy, name: '', + inputs: [ + { + _config: { + type: 'endpoint', + endpointConfig: { + events: { + process: true, + file: false, + network: false, + session_data: false, + }, + }, + }, + }, + ], }, }); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - + const dropDownOptions = [ - {value: "Endpoint", text: "Endpoint"}, - {value: "CloudSecurity", text: "Cloud security"} - ] + { value: 'endpoint', text: 'Endpoint' }, + { value: 'cloud', text: 'Cloud security' }, + ]; const [dropdownValue, setDropdownValue] = useState(dropDownOptions[0].value); - const onChangeDropdown = (e : string) => { - setDropdownValue(e?.target?.value); - } + + const onChangeDropdown = useCallback( + (e: string) => { + setDropdownValue(e?.target?.value); + if (e?.target?.value === 'cloud') { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + _config: { + type: e?.target?.value, + cloudConfig: { + preventions: { + ransomware: false, + malware: false, + }, + }, + }, + eventFilters: { + interactiveSession: true, + }, + }, + ], + }, + }); + } else { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + _config: { + type: e?.target?.value, + endpointConfig: { + events: { + process: true, + file: false, + network: false, + session_data: false, + }, + }, + }, + }, + ], + }, + }); + } + }, + [onChange] + ); const [radioInteractiveSelected, setRadioInteractiveSelected] = useState(true); const [radioComprehensiveSelected, setRadioComprehensiveSelected] = useState(false); - - - const onChangeRadio = () => { - setRadioInteractiveSelected(!radioInteractiveSelected); - setRadioComprehensiveSelected(!radioComprehensiveSelected); - } -/// Endpoint Radio Options (NGAV and EDRs) - const [radioEndpointOption, setRadioEndpointOption] = useState('NGAV') - - const onChangeRadioEndpoint = useCallback ((e) => { - setRadioEndpointOption(e.target.value) - if(e.target.value === 'NGAV'){ - // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs: newPolicy.inputs.concat([{ config : { _create : {policyParams : {value_test: 'NGAV', sessionData: false}}}}])}}) - onChange({isValid:true, updatedPolicy : {...newPolicy}}) - } - else if(e.target.value === 'EDR Essential'){ - // onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Essential', sessionData: false}}}}]}}) - onChange({isValid:true, updatedPolicy : {...newPolicy}}) - } - else if(e.target.value === 'EDR Complete'){ - onChange({isValid:true, updatedPolicy : {...newPolicy, inputs : [{ config : { _create : {policyParams : {value_test: 'EDR Complete', sessionData: true}}}}]}}) + + const onChangeRadio = useCallback(() => { + setRadioInteractiveSelected(!radioInteractiveSelected); + setRadioComprehensiveSelected(!radioComprehensiveSelected); + if (radioInteractiveSelected === true) { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + ...newPolicy.inputs[0], + eventFilters: { + interactiveSession: false, + }, + }, + ], + }, + }); + } else if (radioInteractiveSelected === false) { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + ...newPolicy.inputs[0], + eventFilters: { + interactiveSession: true, + }, + }, + ], + }, + }); } - },[]) -/// + }, [onChange, newPolicy, radioInteractiveSelected, radioComprehensiveSelected]); + + // / Endpoint Radio Options (NGAV and EDRs) + const [radioEndpointOption, setRadioEndpointOption] = useState('NGAV'); + + const onChangeRadioEndpoint = useCallback( + (e) => { + setRadioEndpointOption(e.target.value); + if (e.target.value === 'NGAV') { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + _config: { + // type: 'endpoint', + ...newPolicy.inputs[0]._config, + endpointConfig: { + events: { + process: true, + file: false, + network: false, + session_data: false, + }, + }, + }, + }, + ], + }, + }); + } else if (e.target.value === 'EDR Essential') { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + _config: { + // type: 'endpoint', + ...newPolicy.inputs[0]._config, + endpointConfig: { + events: { + process: true, + file: true, + network: true, + session_data: false, + }, + }, + }, + }, + ], + }, + }); + } else if (e.target.value === 'EDR Complete') { + // onChange({isValid:true, updatedPolicy : {inputs : [{ config : { _create : {policyParams : {type: 'endpoint', sessionData: true}}}}]}}) + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + _config: { + ...newPolicy.inputs[0]._config, + endpointConfig: { + events: { + process: true, + file: true, + network: true, + session_data: true, + }, + }, + }, + }, + ], + }, + }); + } + }, + [onChange, newPolicy] + ); + /// - const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(true); - const [checkboxRansomwareChecked, setCheckboxRansomwareChecked] = useState(true); + const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(false); + const [checkboxRansomwareChecked, setCheckboxRansomwareChecked] = useState(false); - const onChangeMalwareCheckbox = useCallback( () => { - setCheckboxMalwareChecked(!checkboxMalwareChecked) - onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) - },[checkboxMalwareChecked, newPolicy] ) + const onChangeMalwareCheckbox = useCallback(() => { + setCheckboxMalwareChecked(!checkboxMalwareChecked); - const onChangeRansomwareCheckbox = useCallback(() => { - setCheckboxRansomwareChecked(!checkboxRansomwareChecked) - onChange({isValid:'VALID', updatedPolicy : {packagePolicyOnboardingParam : {sessionData: true, protections:{ransomware:!checkboxRansomwareChecked,malware:!checkboxMalwareChecked}}}}) - },[checkboxRansomwareChecked, newPolicy] ) + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + ...newPolicy.inputs[0], + _config: { + ...newPolicy.inputs[0]._config, + cloudConfig: { + ...newPolicy.inputs[0]._config.cloudConfig, + preventions: { + ...newPolicy.inputs[0]._config.cloudConfig.preventions, + malware: !checkboxMalwareChecked, + }, + }, + }, + }, + ], + }, + }); + }, [checkboxMalwareChecked, newPolicy, onChange]); + + const onChangeRansomwareCheckbox = useCallback(() => { + setCheckboxRansomwareChecked(!checkboxRansomwareChecked); + + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + ...newPolicy.inputs[0], + _config: { + ...newPolicy.inputs[0]._config, + cloudConfig: { + ...newPolicy.inputs[0]._config.cloudConfig, + preventions: { + ...newPolicy.inputs[0]._config.cloudConfig.preventions, + ransomware: !checkboxRansomwareChecked, + }, + }, + }, + }, + ], + }, + }); + }, [checkboxRansomwareChecked, newPolicy, onChange]); return ( -
Use quick settings to configure the integration to protect your tranditional endpoints or dynamic clound environments. You can make changes to the configurations after you add it.
- onChangeDropdown(e)} - fullWidth={true} - /> - - {dropdownValue === dropDownOptions[0].value && ( - <> -
Enable prevention
-
In addition to detections, Elastic security can prevent threat before they happen. You can disable detections later in the agent policy configurations settings.
- - + + +
+ +
+
+ +
+ onChangeDropdown(e)} + fullWidth={true} + /> + + {dropdownValue === dropDownOptions[0].value && ( + <> + onChangeRadioEndpoint(e)} - /> - + checked={radioEndpointOption === 'NGAV'} + onChange={(e) => onChangeRadioEndpoint(e)} + /> + - onChangeRadioEndpoint(e)} - /> - + checked={radioEndpointOption === 'EDR Essential'} + onChange={(e) => onChangeRadioEndpoint(e)} + /> + - onChangeRadioEndpoint(e)} - /> - - - )} - - {dropdownValue === dropDownOptions[1].value && ( - <> -
Monitoring mode
- - - onChangeRadioEndpoint(e)} + /> + + + )} + + {dropdownValue === dropDownOptions[1].value && ( + <> +
+ +
+ + + + + + + +
- - - +
+
- - -
Enable Prevention
-
In addition to detections, Elastic security can prevent threats before they happen. You can disable detections anytime in the agent policy configurations settings.
- - - - - - - - - - )} - + id="xpack.fleet.createPackagePolicy.stepConfigure.protectionModeDetailsTranslation" + defaultMessage="In addition to detections, Elastic security can prevent threats before they happen. + You can disable detections anytime in the agent policy configurations settings." + /> +
+ + + + + + + + + + )} +
); } ); EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; - From a947805947d3361522010c776f0de46c45965721 Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Wed, 24 Aug 2022 14:35:02 -0700 Subject: [PATCH 04/28] ui fixes --- .../endpoint_policy_create_extension.tsx | 181 +++++++++++------- 1 file changed, 109 insertions(+), 72 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 4858d6c10b165..229920dc4fceb 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -9,11 +9,71 @@ import React, { memo, useState, useCallback, useEffect } from 'react'; import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; +import styled from 'styled-components' /** * Exports Endpoint-specific package policy instructions * for use in the Ingest app create / edit package policy */ +const SelectConfigurationSettingsText = styled.div` + font-size: 22px; + font-weight: 700; + padding-top: 12px; + padding-bottom: 10px; + line-height: 32px; +`; + +const RadioOptionsDetails = styled.div` + padding-left: 24px; + color: #69707D; + font-weight: 400; + font-size: 12.25px; + line-height: 21px; +`; + +const IntegrationOptionsContainer = styled.div` + margin-bottom: 48px; + margin-top: 17px; +`; + +const CloudOptionDataIngestionMessage = styled.div` + font-size: 14px; + width: max-content; + font-weight: 400; + padding-top: 12px; + padding-bottom: 10px; + color: #69707D; +`; + +const SubduedText = styled.div` + font-size: 14px; + font-weight: 400; + color: #69707D; + line-height: 24px; +`; + +const BoldSubtitle = styled.div` + font-size: 14px; + font-weight: 700; + padding-top: 10px; + padding-bottom: 8px; +`; + +const QuickSettingInfo = styled.div` + padding-bottom: 16px; + font-size: 14px; + line-height: 24px; +`; + +const CloudRadioProtectionsModeContainer = styled.div` + padding-top: 8px; +`; + +const DropDownSelect = styled(EuiSelect)` + margin-top: 14px; +`; + + export const EndpointPolicyCreateExtension = memo( ({ newPolicy, onChange }) => { // Fleet will initialize the create form with a default name for the integratin policy, however, @@ -32,12 +92,7 @@ export const EndpointPolicyCreateExtension = memo -
+ -
-
+ + protect your tranditional endpoints or dynamic clound environments + }} /> -
-
+ -
- + onChangeRadioEndpoint(e)} /> + + onChangeRadioEndpoint(e)} /> + + onChangeRadioEndpoint(e)} /> + + + )} {dropdownValue === dropDownOptions[1].value && ( <> -
+ + -
+ + + + + -
+ -
-
+ + -
+ + + + )} From 1f909d01974b1ec204b8972740a459bfffb816d3 Mon Sep 17 00:00:00 2001 From: kibanamachine <42973632+kibanamachine@users.noreply.github.com> Date: Wed, 24 Aug 2022 22:05:04 +0000 Subject: [PATCH 05/28] [CI] Auto-commit changed files from 'node scripts/eslint --no-cache --fix' --- .../endpoint_policy_create_extension.tsx | 243 +++++++++--------- 1 file changed, 121 insertions(+), 122 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 229920dc4fceb..b488a8551b85a 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -9,23 +9,23 @@ import React, { memo, useState, useCallback, useEffect } from 'react'; import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import styled from 'styled-components' +import styled from 'styled-components'; /** * Exports Endpoint-specific package policy instructions * for use in the Ingest app create / edit package policy */ const SelectConfigurationSettingsText = styled.div` - font-size: 22px; - font-weight: 700; - padding-top: 12px; + font-size: 22px; + font-weight: 700; + padding-top: 12px; padding-bottom: 10px; line-height: 32px; `; const RadioOptionsDetails = styled.div` padding-left: 24px; - color: #69707D; + color: #69707d; font-weight: 400; font-size: 12.25px; line-height: 21px; @@ -42,13 +42,13 @@ const CloudOptionDataIngestionMessage = styled.div` font-weight: 400; padding-top: 12px; padding-bottom: 10px; - color: #69707D; + color: #69707d; `; const SubduedText = styled.div` font-size: 14px; font-weight: 400; - color: #69707D; + color: #69707d; line-height: 24px; `; @@ -60,7 +60,7 @@ const BoldSubtitle = styled.div` `; const QuickSettingInfo = styled.div` - padding-bottom: 16px; + padding-bottom: 16px; font-size: 14px; line-height: 24px; `; @@ -73,7 +73,6 @@ const DropDownSelect = styled(EuiSelect)` margin-top: 14px; `; - export const EndpointPolicyCreateExtension = memo( ({ newPolicy, onChange }) => { // Fleet will initialize the create form with a default name for the integratin policy, however, @@ -315,20 +314,20 @@ export const EndpointPolicyCreateExtension = memo - + protect your tranditional endpoints or dynamic clound environments + value: protect your tranditional endpoints or dynamic clound environments, }} /> - + - - onChangeRadioEndpoint(e)} - /> - - - - - onChangeRadioEndpoint(e)} - /> - - - - - onChangeRadioEndpoint(e)} - /> - - - + + onChangeRadioEndpoint(e)} + /> + + + + + onChangeRadioEndpoint(e)} + /> + + + + + onChangeRadioEndpoint(e)} + /> + + + )} {dropdownValue === dropDownOptions[1].value && ( <> - - - - - - - - - - - - - - + + + + - - - - - + + + + - - - - - + - - - + + + + + + - - - + + + + + + + + + + + )} From 4895884bec02a02169fcf9781ab0d82d7b21888b Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Thu, 25 Aug 2022 11:46:25 -0700 Subject: [PATCH 06/28] linting fix --- .../endpoint_policy_create_extension.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index b488a8551b85a..db2ca023345f1 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -320,7 +320,7 @@ export const EndpointPolicyCreateExtension = memoprotect your tranditional endpoints or dynamic clound environments, + value: {"protect your tranditional endpoints or dynamic clound environments"}, }} /> From ea85e00cd848ade044244843b591b29dd9d6e9ba Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Wed, 31 Aug 2022 11:00:02 -0700 Subject: [PATCH 07/28] edit Fleet endpoint API to allow cloud vs endpoint type integration --- .../server/fleet_integration/constants.ts | 17 +++ .../fleet_integration/fleet_integration.ts | 22 ++- .../handlers/create_default_policy.ts | 135 +++++++++++++++++- .../handlers/validate_integration_config.ts | 71 +++++++++ .../server/fleet_integration/types.ts | 25 ++++ 5 files changed, 266 insertions(+), 4 deletions(-) create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/constants.ts create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/types.ts diff --git a/x-pack/plugins/security_solution/server/fleet_integration/constants.ts b/x-pack/plugins/security_solution/server/fleet_integration/constants.ts new file mode 100644 index 0000000000000..cefa99722fa3e --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/constants.ts @@ -0,0 +1,17 @@ +/* + * 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. + */ + +/** + * Endpoint Security integration presets. + * The default endpoint policy configuration can be overrided based on the preset. + */ + +export const ENDPOINT_CONFIG_PRESET_NGAV = 'NGAV'; +export const ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL = 'EDREssential'; +export const ENDPOINT_CONFIG_PRESET_EDR_COMPLETE = 'EDRComplete'; + +export const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts index e7f21716541cc..a2ae951cfae63 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts @@ -24,10 +24,13 @@ import { installPrepackagedRules } from './handlers/install_prepackaged_rules'; import { createPolicyArtifactManifest } from './handlers/create_policy_artifact_manifest'; import { createDefaultPolicy } from './handlers/create_default_policy'; import { validatePolicyAgainstLicense } from './handlers/validate_policy_against_license'; +import { validateIntegrationConfig } from './handlers/validate_integration_config'; import { removePolicyFromArtifacts } from './handlers/remove_policy_from_artifacts'; import type { FeatureUsageService } from '../endpoint/services/feature_usage/service'; import type { EndpointMetadataService } from '../endpoint/services/metadata'; import { notifyProtectionFeatureUsage } from './notify_protection_feature_usage'; +import type { Config } from './types'; +import { ENDPOINT_INTEGRATION_CONFIG_KEY } from './constants'; const isEndpointPackagePolicy = ( packagePolicy: T @@ -56,6 +59,23 @@ export const getPackagePolicyCreateCallback = ( return newPackagePolicy; } + // Optional endpoint integration configuration + let endpointIntegrationConfig; + + // Check if has endpoint integration configuration input + const integrationConfigInput = newPackagePolicy?.inputs?.find( + (input) => input.type === ENDPOINT_INTEGRATION_CONFIG_KEY + )?.config?._config; + + if (integrationConfigInput !== undefined) { + // The cast below is needed in order to ensure proper typing for the + // Endpoint and Cloud Security integration configuration + endpointIntegrationConfig = integrationConfigInput.value as Config; + + // Validate that the Endpoint and Cloud Security integration config is valid + validateIntegrationConfig(endpointIntegrationConfig, logger); + } + // In this callback we are handling an HTTP request to the fleet plugin. Since we use // code from the security_solution plugin to handle it (installPrepackagedRules), // we need to build the context that is native to security_solution and pass it there. @@ -81,7 +101,7 @@ export const getPackagePolicyCreateCallback = ( ]); // Add the default endpoint security policy - const defaultPolicyValue = createDefaultPolicy(licenseService); + const defaultPolicyValue = createDefaultPolicy(licenseService, endpointIntegrationConfig); return { // We cast the type here so that any changes to the Endpoint diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts index ab01467e75cee..80c0deaa806f1 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts @@ -11,13 +11,142 @@ import { } from '../../../common/endpoint/models/policy_config'; import type { LicenseService } from '../../../common/license/license'; import { isAtLeast } from '../../../common/license/license'; +import { ProtectionModes } from '../../../common/endpoint/types'; import type { PolicyConfig } from '../../../common/endpoint/types'; +import type { Config, CloudConfig, EndpointConfig } from '../types'; +import { ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, ENDPOINT_CONFIG_PRESET_NGAV } from '../constants'; /** - * Create the default endpoint policy based on the current license + * Create the default endpoint policy based on the current license and configuration type */ -export const createDefaultPolicy = (licenseService: LicenseService): PolicyConfig => { - return isAtLeast(licenseService.getLicenseInformation(), 'platinum') +export const createDefaultPolicy = ( + licenseService: LicenseService, + config: Config | undefined +): PolicyConfig => { + const policy = isAtLeast(licenseService.getLicenseInformation(), 'platinum') ? policyConfigFactory() : policyConfigFactoryWithoutPaidFeatures(); + + if (config?.type === 'cloud') { + return getCloudPolicyWithIntegrationConfig(policy, config); + } + + return getEndpointPolicyWithIntegrationConfig(policy, config); +}; + +/** + * Set all keys of the given object to false + */ +const falsyObjectKeys = (obj: Record) => { + return Object.keys(obj).reduce((accumulator, key) => { + return { ...accumulator, [key]: false }; + }, {}); +}; + +/** + * Retrieve policy for endpoint based on the preset selected in the endpoint integration config + */ +const getEndpointPolicyWithIntegrationConfig = ( + policy: PolicyConfig, + config: EndpointConfig | undefined +): PolicyConfig => { + const isEDREssential = config?.endpointConfig?.preset === ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL; + + if (config?.endpointConfig?.preset === ENDPOINT_CONFIG_PRESET_NGAV || isEDREssential) { + const events = { + process: true, + file: isEDREssential, + network: isEDREssential, + }; + + return { + ...policy, + linux: { + ...policy.linux, + events: { + ...(falsyObjectKeys(policy.linux.events) as PolicyConfig['linux']['events']), + ...events, + }, + }, + windows: { + ...policy.windows, + events: { + ...(falsyObjectKeys(policy.windows.events) as PolicyConfig['windows']['events']), + ...events, + }, + }, + mac: { + ...policy.mac, + events: { + ...(falsyObjectKeys(policy.mac.events) as PolicyConfig['mac']['events']), + ...events, + }, + }, + }; + } + + return policy; +}; + +/** + * Retrieve policy for cloud based on the on the cloud integration config + */ +const getCloudPolicyWithIntegrationConfig = ( + policy: PolicyConfig, + config: CloudConfig +): PolicyConfig => { + /** + * Check if the protection is supported, then retrieve Behavior Protection mode based on cloud settings + */ + const getBehaviorProtectionMode = () => { + if (!policy.linux.behavior_protection.supported) { + return ProtectionModes.off; + } + + return config.cloudConfig.preventions.behavior_protection + ? ProtectionModes.prevent + : ProtectionModes.off; + }; + + const protections = { + // Disabling memory_protection, since it's not supported on Cloud integrations + memory_protection: { + supported: false, + mode: ProtectionModes.off, + }, + malware: { + ...policy.linux.malware, + // Malware protection mode based on cloud settings + mode: config.cloudConfig.preventions.malware ? ProtectionModes.prevent : ProtectionModes.off, + }, + behavior_protection: { + ...policy.linux.behavior_protection, + mode: getBehaviorProtectionMode(), + }, + }; + + return { + ...policy, + linux: { + ...policy.linux, + ...protections, + events: { + ...policy.linux.events, + session_data: true, + }, + }, + windows: { + ...policy.windows, + ...protections, + // Disabling ransomware protection, since it's not supported on Cloud integrations + ransomware: { + supported: false, + mode: ProtectionModes.off, + }, + }, + mac: { + ...policy.mac, + ...protections, + }, + }; }; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts new file mode 100644 index 0000000000000..8019d313675cd --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -0,0 +1,71 @@ +/* + * 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 { Logger } from '@kbn/core/server'; +import { + ENDPOINT_CONFIG_PRESET_EDR_COMPLETE, + ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, + ENDPOINT_CONFIG_PRESET_NGAV, +} from '../constants'; +import type { Config, CloudConfig, EndpointConfig } from '../types'; + +// The `statusCode` is used by Fleet API handler to ensure that the proper HTTP code is used in the API response +type THROW_ERROR = Error & { statusCode?: number }; + +const throwError = (message: string): void => { + const error: THROW_ERROR = new Error(message); + error.statusCode = 403; + throw error; +}; + +const validateEndpointIntegrationConfig = (config: EndpointConfig, logger: Logger): void => { + if (!config?.endpointConfig?.preset) { + logger.warn('missing endpointConfig preset'); + throwError('invalid endpointConfig preset'); + } + if ( + ![ + ENDPOINT_CONFIG_PRESET_NGAV, + ENDPOINT_CONFIG_PRESET_EDR_COMPLETE, + ENDPOINT_CONFIG_PRESET_EDR_ESSENTIAL, + ].includes(config.endpointConfig.preset) + ) { + logger.warn(`invalid endpointConfig preset: ${config.endpointConfig.preset}`); + throwError('invalid endpointConfig preset'); + } +}; +const validateCloudIntegrationConfig = (config: CloudConfig, logger: Logger): void => { + if (!config?.cloudConfig?.preventions) { + logger.warn( + 'missing cloudConfig preventions: {preventions : malware: true / false, behavior_protection: true / false}' + ); + throwError('invalid value for cloudConfig: missing preventions '); + } + if (typeof config.cloudConfig.preventions.behavior_protection !== 'boolean') { + logger.warn( + `invalid value for cloudConfig preventions behavior_protection: ${config.cloudConfig.preventions.behavior_protection}` + ); + throwError('invalid value for cloudConfig preventions behavior_protection'); + } + if (typeof config.cloudConfig.preventions.malware !== 'boolean') { + logger.warn( + `invalid value for cloudConfig preventions malware: ${config.cloudConfig.preventions.malware}` + ); + throwError('invalid value for cloudConfig preventions malware'); + } +}; + +export const validateIntegrationConfig = (config: Config, logger: Logger): void => { + if (config.type === 'endpoint') { + validateEndpointIntegrationConfig(config, logger); + } else if (config.type === 'cloud') { + validateCloudIntegrationConfig(config, logger); + } else { + logger.warn(`Invalid integration config type ${config}`); + throwError('Invalid integration config type'); + } +}; diff --git a/x-pack/plugins/security_solution/server/fleet_integration/types.ts b/x-pack/plugins/security_solution/server/fleet_integration/types.ts new file mode 100644 index 0000000000000..cc7627bf8f3a6 --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/types.ts @@ -0,0 +1,25 @@ +/* + * 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. + */ + +export interface EndpointConfig { + type: 'endpoint'; + endpointConfig: { + preset: 'NGAV' | 'EDREssential' | 'EDRComplete'; + }; +} + +export interface CloudConfig { + type: 'cloud'; + cloudConfig: { + preventions: { + malware: boolean; + behavior_protection: boolean; + }; + }; +} + +export type Config = EndpointConfig | CloudConfig; From f0f6ce609fd6aa04a518b26607e2f29d24745ab5 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 12:57:19 -0700 Subject: [PATCH 08/28] adding types for EventFilter --- .../security_solution/server/fleet_integration/types.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/types.ts b/x-pack/plugins/security_solution/server/fleet_integration/types.ts index cc7627bf8f3a6..2ec8728af8191 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/types.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/types.ts @@ -5,6 +5,10 @@ * 2.0. */ +export interface EventFilters { + nonInteractiveSession?: boolean; +} + export interface EndpointConfig { type: 'endpoint'; endpointConfig: { @@ -20,6 +24,7 @@ export interface CloudConfig { behavior_protection: boolean; }; }; + eventFilters?: EventFilters; } export type Config = EndpointConfig | CloudConfig; From 7302935230c761d144e95155d65c1476e05199fa Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 12:57:45 -0700 Subject: [PATCH 09/28] adding event filter validation --- .../handlers/validate_integration_config.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts index 8019d313675cd..ca93ecc5f7cd0 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -57,6 +57,18 @@ const validateCloudIntegrationConfig = (config: CloudConfig, logger: Logger): vo ); throwError('invalid value for cloudConfig preventions malware'); } + if (!config?.eventFilters) { + logger.warn( + `eventFilters is required for cloud integration: {eventFilters : nonInteractiveSession: true / false}` + ); + throwError('eventFilters is required for cloud integration'); + } + if (typeof config.eventFilters?.nonInteractiveSession !== 'boolean') { + logger.warn( + `invalid value for eventFilters nonInteractiveSession: ${config.eventFilters?.nonInteractiveSession}` + ); + throwError('invalid value for eventFilters nonInteractiveSession'); + } }; export const validateIntegrationConfig = (config: Config, logger: Logger): void => { From eaa30cefaa29791eb776cd7d1bafdd8fea6b0804 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 12:58:25 -0700 Subject: [PATCH 10/28] register policy post created callback --- .../endpoint/endpoint_app_context_services.ts | 6 +++ .../fleet_integration/fleet_integration.ts | 41 ++++++++++++++++++- 2 files changed, 45 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts index 3571ffca63b07..59deaae59f450 100644 --- a/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts +++ b/x-pack/plugins/security_solution/server/endpoint/endpoint_app_context_services.ts @@ -22,6 +22,7 @@ import { getPackagePolicyCreateCallback, getPackagePolicyUpdateCallback, getPackagePolicyDeleteCallback, + getPackagePolicyPostCreateCallback, } from '../fleet_integration/fleet_integration'; import type { ManifestManager } from './services/artifacts'; import type { ConfigType } from '../config'; @@ -119,6 +120,11 @@ export class EndpointAppContextService { ) ); + registerIngestCallback( + 'packagePolicyPostCreate', + getPackagePolicyPostCreateCallback(logger, exceptionListsClient) + ); + registerIngestCallback( 'packagePolicyUpdate', getPackagePolicyUpdateCallback( diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts index a2ae951cfae63..a917d1f3cb677 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts @@ -12,10 +12,14 @@ import type { PostPackagePolicyCreateCallback, PostPackagePolicyDeleteCallback, PutPackagePolicyUpdateCallback, + PostPackagePolicyPostCreateCallback, } from '@kbn/fleet-plugin/server'; -import type { NewPackagePolicy, UpdatePackagePolicy } from '@kbn/fleet-plugin/common'; - +import type { + NewPackagePolicy, + PackagePolicy, + UpdatePackagePolicy, +} from '@kbn/fleet-plugin/common'; import type { NewPolicyData, PolicyConfig } from '../../common/endpoint/types'; import type { LicenseService } from '../../common/license'; import type { ManifestManager } from '../endpoint/services'; @@ -31,6 +35,7 @@ import type { EndpointMetadataService } from '../endpoint/services/metadata'; import { notifyProtectionFeatureUsage } from './notify_protection_feature_usage'; import type { Config } from './types'; import { ENDPOINT_INTEGRATION_CONFIG_KEY } from './constants'; +import { createEventFilters } from './handlers/create_event_filters'; const isEndpointPackagePolicy = ( packagePolicy: T @@ -113,6 +118,10 @@ export const getPackagePolicyCreateCallback = ( enabled: true, streams: [], config: { + integration_config: { + value: endpointIntegrationConfig, + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + }, artifact_manifest: { value: manifestValue, }, @@ -156,6 +165,34 @@ export const getPackagePolicyUpdateCallback = ( }; }; +export const getPackagePolicyPostCreateCallback = ( + logger: Logger, + exceptionsClient: ExceptionListClient | undefined +): PostPackagePolicyPostCreateCallback => { + return async (packagePolicy: PackagePolicy): Promise => { + if (!exceptionsClient) { + return packagePolicy; + } + + // We only care about Endpoint package policies + if (!isEndpointPackagePolicy(packagePolicy)) { + return packagePolicy; + } + + const integrationConfig = packagePolicy?.inputs[0].config?.integration_config; + + if (integrationConfig && integrationConfig?.value?.eventFilters !== undefined) { + createEventFilters( + logger, + exceptionsClient, + integrationConfig.value.eventFilters, + packagePolicy + ); + } + return packagePolicy; + }; +}; + export const getPackagePolicyDeleteCallback = ( exceptionsClient: ExceptionListClient | undefined ): PostPackagePolicyDeleteCallback => { From 9aeaf8bc3664bd6447826c529249da81386a6b8e Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 12:58:51 -0700 Subject: [PATCH 11/28] create Event Filters handler --- .../handlers/create_event_filters.ts | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts new file mode 100644 index 0000000000000..993cb882d9755 --- /dev/null +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_event_filters.ts @@ -0,0 +1,84 @@ +/* + * 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 uuid from 'uuid'; +import { i18n } from '@kbn/i18n'; +import { ENDPOINT_EVENT_FILTERS_LIST_ID } from '@kbn/securitysolution-list-constants'; +import type { Logger } from '@kbn/core/server'; +import type { PackagePolicy } from '@kbn/fleet-plugin/common'; +import type { ExceptionListClient } from '@kbn/lists-plugin/server'; +import type { EventFilters } from '../types'; + +const PROCESS_INTERACTIVE_ECS_FIELD = 'process.entry_leader.interactive'; + +/** + * Check if Event Filter list exists and Create Event Filters for the Elastic Defend integration. + */ +export const createEventFilters = async ( + logger: Logger, + exceptionsClient: ExceptionListClient, + eventFilters: EventFilters, + packagePolicy: PackagePolicy +) => { + const exceptionList = await exceptionsClient.getExceptionList({ + id: undefined, + listId: ENDPOINT_EVENT_FILTERS_LIST_ID, + namespaceType: 'agnostic', + }); + + if (exceptionList == null) { + logger.error( + `Error: Exception List not found: ${ENDPOINT_EVENT_FILTERS_LIST_ID}. Event Filter not created.` + ); + } else if (eventFilters.nonInteractiveSession) { + createNonInteractiveSessionEventFilter(logger, exceptionsClient, packagePolicy); + } +}; + +/** + * Create an Event Filter for non-interactive sessions and attach it to the policy + */ +export const createNonInteractiveSessionEventFilter = ( + logger: Logger, + exceptionsClient: ExceptionListClient, + packagePolicy: PackagePolicy +) => { + try { + exceptionsClient.createExceptionListItem({ + listId: ENDPOINT_EVENT_FILTERS_LIST_ID, + description: i18n.translate( + 'xpack.securitySolution.fleetIntegration.elasticDefend.eventFilter.nonInteractiveSessions.description', + { + defaultMessage: 'Event filter for Cloud Security. Created by Elastic Defend integration.', + } + ), + name: i18n.translate( + 'xpack.securitySolution.fleetIntegration.elasticDefend.eventFilter.nonInteractiveSessions.name', + { + defaultMessage: 'Non-interactive Sessions', + } + ), + // Attach to the created policy + tags: [`policy:${packagePolicy.id}`], + osTypes: ['linux'], + type: 'simple', + namespaceType: 'agnostic', + entries: [ + { + field: PROCESS_INTERACTIVE_ECS_FIELD, + operator: 'included', + type: 'match', + value: 'false', + }, + ], + itemId: uuid.v4(), + meta: [], + comments: [], + }); + } catch (err) { + logger.error(`Error: ${err.message}`); + } +}; From 07eded39357f293bbdcc32c0ae11e476f00914fe Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 17:22:52 -0700 Subject: [PATCH 12/28] updating integration config key --- .../server/fleet_integration/fleet_integration.test.ts | 1 + .../server/fleet_integration/fleet_integration.ts | 7 +++---- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts index 0c6611acb77e0..9cae43a23dd8e 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts @@ -82,6 +82,7 @@ describe('ingest_integration tests ', () => { enabled: true, streams: [], config: { + integration_config: {}, policy: { value: policyFactory() }, artifact_manifest: { value: manifest }, }, diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts index a917d1f3cb677..45e3d2a2b36fc 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.ts @@ -118,10 +118,9 @@ export const getPackagePolicyCreateCallback = ( enabled: true, streams: [], config: { - integration_config: { - value: endpointIntegrationConfig, - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - }, + integration_config: endpointIntegrationConfig + ? { value: endpointIntegrationConfig } + : {}, artifact_manifest: { value: manifestValue, }, From 300d2d4da16db8aff0c769d8907aa29bba8ea14f Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 17:23:28 -0700 Subject: [PATCH 13/28] updating event filter validation message --- .../fleet_integration/handlers/validate_integration_config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts index ca93ecc5f7cd0..791359a6108f8 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -65,7 +65,7 @@ const validateCloudIntegrationConfig = (config: CloudConfig, logger: Logger): vo } if (typeof config.eventFilters?.nonInteractiveSession !== 'boolean') { logger.warn( - `invalid value for eventFilters nonInteractiveSession: ${config.eventFilters?.nonInteractiveSession}` + `missing or invalid value for eventFilters nonInteractiveSession: ${config.eventFilters?.nonInteractiveSession}` ); throwError('invalid value for eventFilters nonInteractiveSession'); } From a7d8cd1032875d4d2786582c87c139fc791d1cc4 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 6 Sep 2022 17:33:45 -0700 Subject: [PATCH 14/28] adding tests todo --- .../server/fleet_integration/fleet_integration.test.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts index 9cae43a23dd8e..664abac92db93 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/fleet_integration.test.ts @@ -248,8 +248,13 @@ describe('ingest_integration tests ', () => { expect(manifestManager.pushArtifacts).not.toHaveBeenCalled(); expect(manifestManager.commit).not.toHaveBeenCalled(); }); - }); + it.todo('should override policy config with endpoint settings'); + it.todo('should override policy config with cloud settings'); + }); + describe('package policy post create callback', () => { + it.todo('should create Event Filters given valid parameter on integration config'); + }); describe('package policy update callback (when the license is below platinum)', () => { beforeEach(() => { licenseEmitter.next(Gold); // set license level to gold From 8fe2c86d44c2560b1b0f02345784675b0d091ac1 Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Wed, 7 Sep 2022 11:42:40 -0700 Subject: [PATCH 15/28] fixes + PR comments --- .../endpoint_policy_create_extension.tsx | 363 ++++++++++-------- 1 file changed, 211 insertions(+), 152 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index db2ca023345f1..1f7d00ab2875f 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -7,6 +7,7 @@ import React, { memo, useState, useCallback, useEffect } from 'react'; import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; +import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; import styled from 'styled-components'; @@ -15,6 +16,47 @@ import styled from 'styled-components'; * Exports Endpoint-specific package policy instructions * for use in the Ingest app create / edit package policy */ +// const { euiTheme } = useEuiTheme(); + +const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; + +const ENDPOINT = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + { + defaultMessage: 'Endpoint', + } +); +const CLOUD_SECURITY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudSecurityDropdownOption', + { + defaultMessage: 'Cloud Security', + } +); +const INTERACTIVE_ONLY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersInteractiveOnly', + { + defaultMessage: 'Interactive only', + } +); +const ALL_EVENTS = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersAllEvents', + { + defaultMessage: 'All events', + } +); +const PREVENT_MALWARE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMalware', + { + defaultMessage: 'Prevent Malware', + } +); +const PREVENT_MALICIOUS_BEHAVIOUR = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMaliciousBehaviour', + { + defaultMessage: 'Prevent Malicious Behaviour', + } +); + const SelectConfigurationSettingsText = styled.div` font-size: 22px; font-weight: 700; @@ -25,7 +67,7 @@ const SelectConfigurationSettingsText = styled.div` const RadioOptionsDetails = styled.div` padding-left: 24px; - color: #69707d; + color: ${(props) => props.theme.eui.euiColorDarkShade}; font-weight: 400; font-size: 12.25px; line-height: 21px; @@ -42,13 +84,13 @@ const CloudOptionDataIngestionMessage = styled.div` font-weight: 400; padding-top: 12px; padding-bottom: 10px; - color: #69707d; + color: ${(props) => props.theme.eui.euiColorDarkShade}; `; const SubduedText = styled.div` font-size: 14px; font-weight: 400; - color: #69707d; + color: ${(props) => props.theme.eui.euiColorDarkShade}; line-height: 24px; `; @@ -69,10 +111,19 @@ const CloudRadioProtectionsModeContainer = styled.div` padding-top: 8px; `; -const DropDownSelect = styled(EuiSelect)` - margin-top: 14px; +const PaddingBottomText = styled.div` + padding-bottom: 14px; `; +const dropDownOptions = [ + { value: 'endpoint', text: ENDPOINT }, + { value: 'cloud', text: CLOUD_SECURITY }, +]; + +const NGAV = 'NGAV'; +const EDR_ESSENTIAL = 'EDR Essential'; +const EDR_COMPLETE = 'EDR Complete'; + export const EndpointPolicyCreateExtension = memo( ({ newPolicy, onChange }) => { // Fleet will initialize the create form with a default name for the integratin policy, however, @@ -80,6 +131,74 @@ export const EndpointPolicyCreateExtension = memo { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + ...newPolicy.inputs[0], + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + _config: { + value: { + ...newPolicy.inputs[0]._config.value, + cloudConfig: { + ...newPolicy.inputs[0]._config.value.cloudConfig, + preventions: { + ...newPolicy.inputs[0]._config.value.cloudConfig.preventions, + behavior_protection: statusBehaviour, + malware: statusMalware, + }, + }, + }, + }, + }, + ], + }, + }); + }, + [onChange, newPolicy.inputs] + ); + + const setPreset = useCallback( + (presetValue: string) => { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + _config: { + value: { + ...newPolicy.inputs[0]._config.value, + endpointConfig: { + preset: presetValue, + }, + }, + }, + }, + ], + }, + }); + }, + [onChange, newPolicy.inputs] + ); + useEffect(() => { onChange({ isValid: false, @@ -88,10 +207,15 @@ export const EndpointPolicyCreateExtension = memo { + (e: React.ChangeEvent) => { setDropdownValue(e?.target?.value); if (e?.target?.value === 'cloud') { onChange({ @@ -116,16 +236,21 @@ export const EndpointPolicyCreateExtension = memo { setRadioInteractiveSelected(!radioInteractiveSelected); setRadioComprehensiveSelected(!radioComprehensiveSelected); @@ -165,10 +298,15 @@ export const EndpointPolicyCreateExtension = memo { setRadioEndpointOption(e.target.value); - if (e.target.value === 'NGAV') { - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - _config: { - ...newPolicy.inputs[0]._config, - endpointConfig: { - preset: 'NGAV', - }, - }, - }, - ], - }, - }); - } else if (e.target.value === 'EDR Essential') { - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - _config: { - ...newPolicy.inputs[0]._config, - endpointConfig: { - preset: 'EDREssential', - }, - }, - }, - ], - }, - }); - } else if (e.target.value === 'EDR Complete') { - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - _config: { - ...newPolicy.inputs[0]._config, - endpointConfig: { - preset: 'EDRComplete', - }, - }, - }, - ], - }, - }); - } + setPreset(e.target.value); }, - [onChange, newPolicy] + [setPreset] ); /// - const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(false); - const [checkboxRansomwareChecked, setCheckboxRansomwareChecked] = useState(false); - const onChangeMalwareCheckbox = useCallback(() => { setCheckboxMalwareChecked(!checkboxMalwareChecked); - - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - ...newPolicy.inputs[0], - _config: { - ...newPolicy.inputs[0]._config, - cloudConfig: { - ...newPolicy.inputs[0]._config.cloudConfig, - preventions: { - ...newPolicy.inputs[0]._config.cloudConfig.preventions, - malware: !checkboxMalwareChecked, - }, - }, - }, - }, - ], - }, - }); - }, [checkboxMalwareChecked, newPolicy, onChange]); + setPreventions(checkboxMaliciousChecked, !checkboxMalwareChecked); + }, [checkboxMalwareChecked, checkboxMaliciousChecked, setPreventions]); const onChangeRansomwareCheckbox = useCallback(() => { - setCheckboxRansomwareChecked(!checkboxRansomwareChecked); - - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - ...newPolicy.inputs[0], - _config: { - ...newPolicy.inputs[0]._config, - cloudConfig: { - ...newPolicy.inputs[0]._config.cloudConfig, - preventions: { - ...newPolicy.inputs[0]._config.cloudConfig.preventions, - ransomware: !checkboxRansomwareChecked, - }, - }, - }, - }, - ], - }, - }); - }, [checkboxRansomwareChecked, newPolicy, onChange]); + setCheckboxMaliciousChecked(!checkboxMaliciousChecked); + setPreventions(!checkboxMaliciousChecked, checkboxMalwareChecked); + }, [checkboxMalwareChecked, checkboxMaliciousChecked, setPreventions]); return ( @@ -318,17 +368,26 @@ export const EndpointPolicyCreateExtension = memo {"protect your tranditional endpoints or dynamic clound environments"}, + environments: ( + + + + ), }} /> - - + + + onChangeRadioEndpoint(e)} /> @@ -373,8 +432,8 @@ export const EndpointPolicyCreateExtension = memo onChangeRadioEndpoint(e)} /> @@ -399,7 +458,7 @@ export const EndpointPolicyCreateExtension = memo @@ -412,7 +471,7 @@ export const EndpointPolicyCreateExtension = memo @@ -441,16 +500,16 @@ export const EndpointPolicyCreateExtension = memo From df51d8486f0e1dfe13687eda725b021aed29a4eb Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Thu, 8 Sep 2022 12:38:48 -0700 Subject: [PATCH 16/28] more PR comments --- .../endpoint_policy_create_extension.tsx | 101 ++++++++---------- 1 file changed, 44 insertions(+), 57 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 1f7d00ab2875f..f42a8ece378fc 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -20,6 +20,20 @@ import styled from 'styled-components'; const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; +const NGAV = 'NGAV'; +const EDR_ESSENTIAL = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + { + defaultMessage: 'EDR Essential', + } +); +const EDR_COMPLETE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + { + defaultMessage: 'EDR Complete', + } +); + const ENDPOINT = i18n.translate( 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', { @@ -120,10 +134,6 @@ const dropDownOptions = [ { value: 'cloud', text: CLOUD_SECURITY }, ]; -const NGAV = 'NGAV'; -const EDR_ESSENTIAL = 'EDR Essential'; -const EDR_COMPLETE = 'EDR Complete'; - export const EndpointPolicyCreateExtension = memo( ({ newPolicy, onChange }) => { // Fleet will initialize the create form with a default name for the integratin policy, however, @@ -292,49 +302,26 @@ export const EndpointPolicyCreateExtension = memo { setRadioInteractiveSelected(!radioInteractiveSelected); setRadioComprehensiveSelected(!radioComprehensiveSelected); - if (radioInteractiveSelected === true) { - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - _config: { - value: { - ...newPolicy.inputs[0]._config.value, - eventFilters: { - nonInteractiveSession: true, - }, - }, - }, - }, - ], - }, - }); - } else if (radioInteractiveSelected === false) { - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - _config: { - value: { - ...newPolicy.inputs[0]._config.value, - eventFilters: { - nonInteractiveSession: false, - }, + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + _config: { + value: { + ...newPolicy.inputs[0]._config.value, + eventFilters: { + nonInteractiveSession: radioInteractiveSelected, }, }, }, - ], - }, - }); - } + }, + ], + }, + }); }, [onChange, newPolicy, radioInteractiveSelected, radioComprehensiveSelected]); const onChangeRadioEndpoint = useCallback( @@ -361,13 +348,13 @@ export const EndpointPolicyCreateExtension = memo @@ -408,14 +395,14 @@ export const EndpointPolicyCreateExtension = memo @@ -451,7 +438,7 @@ export const EndpointPolicyCreateExtension = memo @@ -464,7 +451,7 @@ export const EndpointPolicyCreateExtension = memo @@ -477,20 +464,20 @@ export const EndpointPolicyCreateExtension = memo From c3a3a9e856401d2953d2b28f2e0c3e1cc130f650 Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Thu, 8 Sep 2022 13:11:21 -0700 Subject: [PATCH 17/28] Check fail fixes --- .../endpoint_policy_create_extension.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index f42a8ece378fc..facdcda1e490c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -22,13 +22,13 @@ const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; const NGAV = 'NGAV'; const EDR_ESSENTIAL = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDREssential', { defaultMessage: 'EDR Essential', } ); const EDR_COMPLETE = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDRComplete', { defaultMessage: 'EDR Complete', } From db25d947af2b8857c7df9603d85b4c62b4feb62d Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Fri, 9 Sep 2022 12:09:59 -0700 Subject: [PATCH 18/28] more PR comments --- .../endpoint_policy_create_extension.tsx | 171 ++++++++++-------- 1 file changed, 98 insertions(+), 73 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index facdcda1e490c..71c3aaae49e1c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -11,12 +11,12 @@ import { i18n } from '@kbn/i18n'; import { FormattedMessage } from '@kbn/i18n-react'; import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; import styled from 'styled-components'; +import { useLicense } from '../../../../../common/hooks/use_license'; /** * Exports Endpoint-specific package policy instructions * for use in the Ingest app create / edit package policy */ -// const { euiTheme } = useEuiTheme(); const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; @@ -140,6 +140,8 @@ export const EndpointPolicyCreateExtension = memo { @@ -162,15 +164,17 @@ export const EndpointPolicyCreateExtension = memo { + onChange({ + isValid: true, + updatedPolicy: { + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + config: { + _config: { + value: { + ...newPolicy.inputs[0].config._config.value, + eventFilters: { + nonInteractiveSession: interactiveStatus, + }, }, }, }, @@ -220,11 +254,13 @@ export const EndpointPolicyCreateExtension = memo { setRadioInteractiveSelected(!radioInteractiveSelected); setRadioComprehensiveSelected(!radioComprehensiveSelected); - onChange({ - isValid: true, - updatedPolicy: { - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - _config: { - value: { - ...newPolicy.inputs[0]._config.value, - eventFilters: { - nonInteractiveSession: radioInteractiveSelected, - }, - }, - }, - }, - ], - }, - }); - }, [onChange, newPolicy, radioInteractiveSelected, radioComprehensiveSelected]); + setInteractive(!radioComprehensiveSelected); + }, [radioInteractiveSelected, radioComprehensiveSelected, setInteractive]); const onChangeRadioEndpoint = useCallback( - // Add value check here ? (e) => { setRadioEndpointOption(e.target.value); setPreset(e.target.value); @@ -404,8 +427,8 @@ export const EndpointPolicyCreateExtension = memo onChangeRadioEndpoint(e)} /> @@ -419,8 +442,8 @@ export const EndpointPolicyCreateExtension = memo onChangeRadioEndpoint(e)} /> @@ -492,14 +515,16 @@ export const EndpointPolicyCreateExtension = memo - - - + {isPlatinumPlus && ( + + + + )} From 3e1fbd1c4e2e29b42f361de03d52d640509d01dc Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Mon, 12 Sep 2022 10:01:53 -0700 Subject: [PATCH 19/28] edited payload --- .../endpoint_policy_create_extension.tsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 71c3aaae49e1c..4f36baa23c74c 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -172,7 +172,7 @@ export const EndpointPolicyCreateExtension = memo Date: Mon, 12 Sep 2022 22:55:23 -0700 Subject: [PATCH 20/28] checks error fix --- .../endpoint_policy_create_extension.tsx | 22 ++++++++++++------- .../translations/translations/fr-FR.json | 1 - .../translations/translations/ja-JP.json | 1 - .../translations/translations/zh-CN.json | 1 - 4 files changed, 14 insertions(+), 11 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 4f36baa23c74c..ca797a96bdd28 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -158,6 +158,7 @@ export const EndpointPolicyCreateExtension = memo { @@ -280,6 +283,7 @@ export const EndpointPolicyCreateExtension = memo Date: Mon, 12 Sep 2022 23:18:52 -0700 Subject: [PATCH 21/28] check fixes --- .../endpoint_policy_create_extension.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index ca797a96bdd28..929e2ededf5c6 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -172,7 +172,7 @@ export const EndpointPolicyCreateExtension = memo Date: Tue, 13 Sep 2022 13:05:06 -0700 Subject: [PATCH 22/28] bug fix for filters --- .../endpoint_policy_create_extension.tsx | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 929e2ededf5c6..094991f3338bf 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -150,8 +150,8 @@ export const EndpointPolicyCreateExtension = memo { @@ -296,12 +296,11 @@ export const EndpointPolicyCreateExtension = memo { setRadioInteractiveSelected(!radioInteractiveSelected); setRadioComprehensiveSelected(!radioComprehensiveSelected); - setInteractive(!radioComprehensiveSelected); + setInteractive(radioComprehensiveSelected); }, [radioInteractiveSelected, radioComprehensiveSelected, setInteractive]); const onChangeRadioEndpoint = useCallback( From 242c4904677df345aecf658d53057d1e671e8fdb Mon Sep 17 00:00:00 2001 From: Ricky Ang Date: Tue, 13 Sep 2022 13:07:57 -0700 Subject: [PATCH 23/28] eslint stuff --- .../endpoint_policy_create_extension.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx index 094991f3338bf..8a15d8193d6b7 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx @@ -340,8 +340,8 @@ export const EndpointPolicyCreateExtension = memo Date: Mon, 19 Sep 2022 17:08:03 -0700 Subject: [PATCH 24/28] refactoring ui component --- .../endpoint_policy_create_extension.tsx | 540 ------------------ .../endpoint_policy_create_extension.tsx | 354 ++++++++++++ .../index.tsx | 8 + .../translations.ts | 65 +++ 4 files changed, 427 insertions(+), 540 deletions(-) delete mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx create mode 100644 x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx deleted file mode 100644 index 8a15d8193d6b7..0000000000000 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension.tsx +++ /dev/null @@ -1,540 +0,0 @@ -/* - * 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, useState, useCallback, useEffect } from 'react'; -import { EuiForm, EuiFlexGroup, EuiFlexItem, EuiCheckbox, EuiRadio, EuiSelect } from '@elastic/eui'; -import { i18n } from '@kbn/i18n'; -import { FormattedMessage } from '@kbn/i18n-react'; -import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; -import styled from 'styled-components'; -import { useLicense } from '../../../../../common/hooks/use_license'; - -/** - * Exports Endpoint-specific package policy instructions - * for use in the Ingest app create / edit package policy - */ - -const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; - -const NGAV = 'NGAV'; -const EDR_ESSENTIAL = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDREssential', - { - defaultMessage: 'EDR Essential', - } -); -const EDR_COMPLETE = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDRComplete', - { - defaultMessage: 'EDR Complete', - } -); - -const ENDPOINT = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', - { - defaultMessage: 'Endpoint', - } -); -const CLOUD_SECURITY = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudSecurityDropdownOption', - { - defaultMessage: 'Cloud Security', - } -); -const INTERACTIVE_ONLY = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersInteractiveOnly', - { - defaultMessage: 'Interactive only', - } -); -const ALL_EVENTS = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersAllEvents', - { - defaultMessage: 'All events', - } -); -const PREVENT_MALWARE = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMalware', - { - defaultMessage: 'Prevent Malware', - } -); -const PREVENT_MALICIOUS_BEHAVIOUR = i18n.translate( - 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMaliciousBehaviour', - { - defaultMessage: 'Prevent Malicious Behaviour', - } -); - -const SelectConfigurationSettingsText = styled.div` - font-size: 22px; - font-weight: 700; - padding-top: 12px; - padding-bottom: 10px; - line-height: 32px; -`; - -const RadioOptionsDetails = styled.div` - padding-left: 24px; - color: ${(props) => props.theme.eui.euiColorDarkShade}; - font-weight: 400; - font-size: 12.25px; - line-height: 21px; -`; - -const IntegrationOptionsContainer = styled.div` - margin-bottom: 48px; - margin-top: 17px; -`; - -const CloudOptionDataIngestionMessage = styled.div` - font-size: 14px; - width: max-content; - font-weight: 400; - padding-top: 12px; - padding-bottom: 10px; - color: ${(props) => props.theme.eui.euiColorDarkShade}; -`; - -const SubduedText = styled.div` - font-size: 14px; - font-weight: 400; - color: ${(props) => props.theme.eui.euiColorDarkShade}; - line-height: 24px; -`; - -const BoldSubtitle = styled.div` - font-size: 14px; - font-weight: 700; - padding-top: 10px; - padding-bottom: 8px; -`; - -const QuickSettingInfo = styled.div` - padding-bottom: 16px; - font-size: 14px; - line-height: 24px; -`; - -const CloudRadioProtectionsModeContainer = styled.div` - padding-top: 8px; -`; - -const PaddingBottomText = styled.div` - padding-bottom: 14px; -`; - -const dropDownOptions = [ - { value: 'endpoint', text: ENDPOINT }, - { value: 'cloud', text: CLOUD_SECURITY }, -]; - -export const EndpointPolicyCreateExtension = memo( - ({ newPolicy, onChange }) => { - // Fleet will initialize the create form with a default name for the integratin policy, however, - // for endpoint security, we want the user to explicitely type in a name, so we blank it out - // only during 1st component render (thus why the eslint disabled rule below). - - const isPlatinumPlus = useLicense().isPlatinumPlus(); - - // Run useEffect when page 1st load, default value are endpoint + NGAV - - // / Endpoint Radio Options (NGAV and EDRs) - const [radioEndpointOption, setRadioEndpointOption] = useState(NGAV); - - const [checkboxMalwareChecked, setCheckboxMalwareChecked] = useState(false); - const [checkboxMaliciousChecked, setCheckboxMaliciousChecked] = useState(false); - - const [radioInteractiveSelected, setRadioInteractiveSelected] = useState(true); - const [radioComprehensiveSelected, setRadioComprehensiveSelected] = useState(false); - - const setPreventions = useCallback( - (statusBehaviour: boolean, statusMalware: boolean) => { - onChange({ - isValid: true, - updatedPolicy: { - ...newPolicy, - inputs: [ - { - ...newPolicy.inputs[0], - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - ...newPolicy?.inputs[0]?.config?._config?.value, - cloudConfig: { - ...newPolicy?.inputs[0]?.config?._config?.value?.cloudConfig, - preventions: { - ...newPolicy?.inputs[0]?.config?._config?.value?.cloudConfig?.preventions, - behavior_protection: statusBehaviour, - malware: statusMalware, - }, - }, - }, - }, - }, - }, - ], - }, - }); - }, - [onChange, newPolicy] - ); - - const setPreset = useCallback( - (presetValue: string) => { - onChange({ - isValid: true, - updatedPolicy: { - ...newPolicy, - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - ...newPolicy?.inputs[0]?.config?._config?.value, - endpointConfig: { - preset: presetValue, - }, - }, - }, - }, - }, - ], - }, - }); - }, - [onChange, newPolicy] - ); - - const setInteractive = useCallback( - (interactiveStatus: boolean) => { - onChange({ - isValid: true, - updatedPolicy: { - ...newPolicy, - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - ...newPolicy?.inputs[0]?.config?._config?.value, - eventFilters: { - nonInteractiveSession: interactiveStatus, - }, - }, - }, - }, - }, - ], - }, - }); - }, - [onChange, newPolicy] - ); - - useEffect(() => { - onChange({ - isValid: false, - updatedPolicy: { - ...newPolicy, - name: '', - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - type: 'endpoint', - endpointConfig: { - preset: 'NGAV', - }, - }, - }, - }, - }, - ], - }, - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - const [dropdownValue, setDropdownValue] = useState(dropDownOptions[0].value); - - const onChangeDropdown = useCallback( - (e: React.ChangeEvent) => { - setDropdownValue(e?.target?.value); - if (e?.target?.value === 'cloud') { - onChange({ - isValid: true, - updatedPolicy: { - ...newPolicy, - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - type: e?.target?.value, - cloudConfig: { - preventions: { - behavior_protection: checkboxMaliciousChecked, - malware: checkboxMalwareChecked, - }, - }, - eventFilters: { - nonInteractiveSession: radioInteractiveSelected, - }, - }, - }, - }, - }, - ], - }, - }); - } else { - onChange({ - isValid: true, - updatedPolicy: { - ...newPolicy, - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - type: e?.target?.value, - endpointConfig: { - preset: radioEndpointOption, - }, - }, - }, - }, - }, - ], - }, - }); - } - }, - [ - onChange, - radioEndpointOption, - checkboxMaliciousChecked, - checkboxMalwareChecked, - newPolicy, - radioInteractiveSelected, - ] - ); - - const onChangeRadio = useCallback(() => { - setRadioInteractiveSelected(!radioInteractiveSelected); - setRadioComprehensiveSelected(!radioComprehensiveSelected); - setInteractive(radioComprehensiveSelected); - }, [radioInteractiveSelected, radioComprehensiveSelected, setInteractive]); - - const onChangeRadioEndpoint = useCallback( - (e) => { - setRadioEndpointOption(e.target.value); - setPreset(e.target.value); - }, - [setPreset] - ); - /// - - const onChangeMalwareCheckbox = useCallback(() => { - setCheckboxMalwareChecked(!checkboxMalwareChecked); - setPreventions(checkboxMaliciousChecked, !checkboxMalwareChecked); - }, [checkboxMalwareChecked, checkboxMaliciousChecked, setPreventions]); - - const onChangeRansomwareCheckbox = useCallback(() => { - setCheckboxMaliciousChecked(!checkboxMaliciousChecked); - setPreventions(!checkboxMaliciousChecked, checkboxMalwareChecked); - }, [checkboxMalwareChecked, checkboxMaliciousChecked, setPreventions]); - - return ( - - - - - - - - - ), - }} - /> - - - - - onChangeDropdown(e)} - fullWidth={true} - /> - - {dropdownValue === dropDownOptions[0].value && ( - <> - - onChangeRadioEndpoint(e)} - /> - - - - - onChangeRadioEndpoint(e)} - /> - - - - - onChangeRadioEndpoint(e)} - /> - - - - - - )} - - {dropdownValue === dropDownOptions[1].value && ( - <> - - - - - - - - - - - - - - - - - - - - - - - - - - - {isPlatinumPlus && ( - - - - )} - - - - - )} - - ); - } -); -EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx new file mode 100644 index 0000000000000..a8d302affd7f3 --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -0,0 +1,354 @@ +/* + * 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, useState, useEffect, useRef } from 'react'; +import { + EuiForm, + EuiCheckbox, + EuiRadio, + EuiSelect, + EuiText, + EuiTitle, + EuiSpacer, + EuiFormRow, +} from '@elastic/eui'; +import { FormattedMessage } from '@kbn/i18n-react'; +import styled from 'styled-components'; +import type { PackagePolicyCreateExtensionComponentProps } from '@kbn/fleet-plugin/public'; +import { useLicense } from '../../../../../../common/hooks/use_license'; +import { + ALL_EVENTS, + CLOUD_SECURITY, + EDR_COMPLETE, + NGAV, + EDR_ESSENTIAL, + ENDPOINT, + INTERACTIVE_ONLY, + PREVENT_MALICIOUS_BEHAVIOUR, +} from './translations'; + +const PREFIX = 'endpoint_policy_create_extension'; + +const ENDPOINT_INTEGRATION_CONFIG_KEY = 'ENDPOINT_INTEGRATION_CONFIG'; + +const environmentMapping = { + cloud: CLOUD_SECURITY, + endpoint: ENDPOINT, +}; + +const endpointPresetsMapping = { + NGAV, + EDREssential: EDR_ESSENTIAL, + EDRComplete: EDR_COMPLETE, +}; + +const cloudEventMapping = { + INTERACTIVE_ONLY, + ALL_EVENTS, +}; + +type EndpointPreset = keyof typeof endpointPresetsMapping; +type CloudEvent = keyof typeof cloudEventMapping; +type Environment = keyof typeof environmentMapping; + +const environmentOptions: Array<{ value: Environment; text: string }> = [ + { value: 'endpoint', text: ENDPOINT }, + { value: 'cloud', text: CLOUD_SECURITY }, +]; + +const HelpTextWithPadding = styled.div` + padding-left: ${(props) => props.theme.eui.euiSizeL}; +`; + +/** + * Exports Endpoint-specific package policy instructions + * for use in the Ingest app create / edit package policy + */ +export const EndpointPolicyCreateExtension = memo( + ({ newPolicy, onChange }) => { + const isPlatinumPlus = useLicense().isPlatinumPlus(); + + // / Endpoint Radio Options (NGAV and EDRs) + const [endpointPreset, setEndpointPreset] = useState('NGAV'); + const [behaviorProtectionChecked, setBehaviorProtectionChecked] = useState(false); + const [selectedCloudEvent, setSelectedCloudEvent] = useState('INTERACTIVE_ONLY'); + const [selectedEnvironment, setSelectedEnvironment] = useState('endpoint'); + const initialRender = useRef(true); + + // Fleet will initialize the create form with a default name for the integratin policy, however, + // for endpoint security, we want the user to explicitely type in a name, so we blank it out + // only during 1st component render (thus why the eslint disabled rule below). + // Default values for config are endpoint + NGAV + useEffect(() => { + onChange({ + isValid: false, + updatedPolicy: { + ...newPolicy, + name: '', + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + config: { + _config: { + value: { + type: 'endpoint', + endpointConfig: { + preset: 'NGAV', + }, + }, + }, + }, + }, + ], + }, + }); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + useEffect(() => { + // Skip trigerring this onChange on the initial render + if (initialRender.current) { + initialRender.current = false; + } else { + onChange({ + isValid: true, + updatedPolicy: { + ...newPolicy, + inputs: [ + { + ...newPolicy.inputs[0], + config: { + _config: { + value: { + type: selectedEnvironment, + ...(selectedEnvironment === 'cloud' + ? { + cloudConfig: { + preventions: { + behavior_protection: behaviorProtectionChecked, + }, + }, + eventFilters: { + nonInteractiveSession: selectedCloudEvent === 'INTERACTIVE_ONLY', + }, + } + : { + endpointConfig: { + preset: endpointPreset, + }, + }), + }, + }, + }, + }, + ], + }, + }); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedEnvironment, behaviorProtectionChecked, selectedCloudEvent, endpointPreset]); + + const onChangeEnvironment = (e: React.ChangeEvent) => { + setSelectedEnvironment(e?.target?.value as Environment); + }; + const onChangeCloudEvent = (e: React.ChangeEvent) => { + setSelectedCloudEvent(e.target.value as CloudEvent); + }; + const onChangeEndpointPreset = (e: React.ChangeEvent) => { + setEndpointPreset(e.target.value as EndpointPreset); + }; + const onChangeMaliciousBehavior = (e: React.ChangeEvent) => { + setBehaviorProtectionChecked(!behaviorProtectionChecked); + }; + + const getEndpointPresetsProps = (preset: EndpointPreset) => ({ + id: `${PREFIX}_endpoint_preset_${preset}`, + label: endpointPresetsMapping[preset], + value: preset, + checked: endpointPreset === preset, + onChange: onChangeEndpointPreset, + }); + + const getCloudEventsProps = (cloudEvent: CloudEvent) => ({ + id: `${PREFIX}_cloud_event_${cloudEvent}`, + label: cloudEventMapping[cloudEvent], + value: cloudEvent, + checked: selectedCloudEvent === cloudEvent, + onChange: onChangeCloudEvent, + }); + + return ( + + +

+ +

+
+ + +

+ + + + ), + }} + /> +

+
+ + + } + > + + + {selectedEnvironment === 'endpoint' ? ( + <> + + + + + } + > + + + + + + + } + > + + + + + + + } + > + + + + ) : ( + <> + + +

+ +

+
+ + + + + } + > + + + + + + + } + > + + + {isPlatinumPlus && ( + <> + + +

+ +

+
+ + +

+ +

+
+ + + + )} + + )} + +
+ ); + } +); +EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx new file mode 100644 index 0000000000000..9be04def1c64e --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/index.tsx @@ -0,0 +1,8 @@ +/* + * 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. + */ + +export { EndpointPolicyCreateExtension } from './endpoint_policy_create_extension'; diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts new file mode 100644 index 0000000000000..b50835b36995b --- /dev/null +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/translations.ts @@ -0,0 +1,65 @@ +/* + * 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 { i18n } from '@kbn/i18n'; + +export const NGAV = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionNGAV', + { + defaultMessage: 'NGAV', + } +); + +export const EDR_ESSENTIAL = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDREssential', + { + defaultMessage: 'EDR Essential', + } +); +export const EDR_COMPLETE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOptionEDRComplete', + { + defaultMessage: 'EDR Complete', + } +); + +export const ENDPOINT = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.endpointDropdownOption', + { + defaultMessage: 'Endpoint', + } +); +export const CLOUD_SECURITY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudSecurityDropdownOption', + { + defaultMessage: 'Cloud Security', + } +); +export const INTERACTIVE_ONLY = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersInteractiveOnly', + { + defaultMessage: 'Interactive only', + } +); +export const ALL_EVENTS = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersAllEvents', + { + defaultMessage: 'All events', + } +); +export const PREVENT_MALWARE = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMalware', + { + defaultMessage: 'Prevent Malware', + } +); +export const PREVENT_MALICIOUS_BEHAVIOUR = i18n.translate( + 'xpack.securitySolution.createPackagePolicy.stepConfigure.cloudEventFiltersPreventionMaliciousBehaviour', + { + defaultMessage: 'Prevent Malicious Behaviour', + } +); From bc3a70b6500c68e92df189e154517b6e9f241d90 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Mon, 19 Sep 2022 17:09:08 -0700 Subject: [PATCH 25/28] disabling malware for cloud settings --- .../fleet_integration/handlers/create_default_policy.ts | 4 ++-- .../handlers/validate_integration_config.ts | 8 +------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts index 47b4840665e64..8ffd33e070d98 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/create_default_policy.ts @@ -120,8 +120,8 @@ const getCloudPolicyWithIntegrationConfig = ( }, malware: { ...policy.linux.malware, - // Malware protection mode based on cloud settings - mode: config.cloudConfig.preventions.malware ? ProtectionModes.prevent : ProtectionModes.off, + // Disabling Malware protection, since it's not supported on Cloud integrations due to performance reasons + mode: ProtectionModes.off, }, behavior_protection: { ...policy.linux.behavior_protection, diff --git a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts index d56dd6a02d4cd..76bd3e8af93fb 100644 --- a/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts +++ b/x-pack/plugins/security_solution/server/fleet_integration/handlers/validate_integration_config.ts @@ -48,7 +48,7 @@ const validateEndpointIntegrationConfig = ( const validateCloudIntegrationConfig = (config: PolicyCreateCloudConfig, logger: Logger): void => { if (!config?.cloudConfig?.preventions) { logger.warn( - 'missing cloudConfig preventions: {preventions : malware: true / false, behavior_protection: true / false}' + 'missing cloudConfig preventions: {preventions : behavior_protection: true / false}' ); throwError('invalid value for cloudConfig: missing preventions '); } @@ -58,12 +58,6 @@ const validateCloudIntegrationConfig = (config: PolicyCreateCloudConfig, logger: ); throwError('invalid value for cloudConfig preventions behavior_protection'); } - if (typeof config.cloudConfig.preventions.malware !== 'boolean') { - logger.warn( - `invalid value for cloudConfig preventions malware: ${config.cloudConfig.preventions.malware}` - ); - throwError('invalid value for cloudConfig preventions malware'); - } if (!config?.eventFilters) { logger.warn( `eventFilters is required for cloud integration: {eventFilters : nonInteractiveSession: true / false}` From 2715e43450047c83dfada657ab56005afbd58ef9 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Mon, 19 Sep 2022 17:11:32 -0700 Subject: [PATCH 26/28] addressing text change comments --- .../endpoint_policy_create_extension.tsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx index a8d302affd7f3..9300e85b7b4c3 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -198,7 +198,7 @@ export const EndpointPolicyCreateExtension = memo @@ -218,7 +218,7 @@ export const EndpointPolicyCreateExtension = memo } > @@ -282,7 +282,7 @@ export const EndpointPolicyCreateExtension = memo

@@ -331,7 +331,7 @@ export const EndpointPolicyCreateExtension = memo

From ee46fe9a9bd8121daf843b5ca7a6c6959dd10710 Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 20 Sep 2022 10:36:51 -0700 Subject: [PATCH 27/28] adding useCallbacks and memoization, fixing deps list --- .../endpoint_policy_create_extension.tsx | 67 ++++++++++++------- 1 file changed, 41 insertions(+), 26 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx index 9300e85b7b4c3..15f78de240637 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -5,7 +5,7 @@ * 2.0. */ -import React, { memo, useState, useEffect, useRef } from 'react'; +import React, { memo, useState, useEffect, useRef, useCallback } from 'react'; import { EuiForm, EuiCheckbox, @@ -151,37 +151,49 @@ export const EndpointPolicyCreateExtension = memo) => { + const onChangeEnvironment = useCallback((e: React.ChangeEvent) => { setSelectedEnvironment(e?.target?.value as Environment); - }; - const onChangeCloudEvent = (e: React.ChangeEvent) => { + }, []); + const onChangeCloudEvent = useCallback((e: React.ChangeEvent) => { setSelectedCloudEvent(e.target.value as CloudEvent); - }; - const onChangeEndpointPreset = (e: React.ChangeEvent) => { + }, []); + const onChangeEndpointPreset = useCallback((e: React.ChangeEvent) => { setEndpointPreset(e.target.value as EndpointPreset); - }; - const onChangeMaliciousBehavior = (e: React.ChangeEvent) => { - setBehaviorProtectionChecked(!behaviorProtectionChecked); - }; + }, []); + const onChangeMaliciousBehavior = useCallback((e: React.ChangeEvent) => { + setBehaviorProtectionChecked((checked) => !checked); + }, []); - const getEndpointPresetsProps = (preset: EndpointPreset) => ({ - id: `${PREFIX}_endpoint_preset_${preset}`, - label: endpointPresetsMapping[preset], - value: preset, - checked: endpointPreset === preset, - onChange: onChangeEndpointPreset, - }); + const getEndpointPresetsProps = useCallback( + (preset: EndpointPreset) => ({ + id: `${PREFIX}_endpoint_preset_${preset}`, + label: endpointPresetsMapping[preset], + value: preset, + checked: endpointPreset === preset, + onChange: onChangeEndpointPreset, + }), + [endpointPreset, onChangeEndpointPreset] + ); - const getCloudEventsProps = (cloudEvent: CloudEvent) => ({ - id: `${PREFIX}_cloud_event_${cloudEvent}`, - label: cloudEventMapping[cloudEvent], - value: cloudEvent, - checked: selectedCloudEvent === cloudEvent, - onChange: onChangeCloudEvent, - }); + const getCloudEventsProps = useCallback( + (cloudEvent: CloudEvent) => ({ + id: `${PREFIX}_cloud_event_${cloudEvent}`, + label: cloudEventMapping[cloudEvent], + value: cloudEvent, + checked: selectedCloudEvent === cloudEvent, + onChange: onChangeCloudEvent, + }), + [selectedCloudEvent, onChangeCloudEvent] + ); return ( @@ -349,6 +361,9 @@ export const EndpointPolicyCreateExtension = memo ); + }, + (prevProps, nextProps) => { + return prevProps.newPolicy.name === nextProps.newPolicy.name; } ); EndpointPolicyCreateExtension.displayName = 'EndpointPolicyCreateExtension'; From 25be98a0b6806961b1bb9e54abc6ad584178869f Mon Sep 17 00:00:00 2001 From: Paulo Henrique Date: Tue, 20 Sep 2022 10:42:21 -0700 Subject: [PATCH 28/28] removing deps ignore --- .../endpoint_policy_create_extension.tsx | 45 ++++++++++--------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx index 15f78de240637..9a4dc273740e5 100644 --- a/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx +++ b/x-pack/plugins/security_solution/public/management/pages/policy/view/ingest_manager_integration/endpoint_policy_create_extension/endpoint_policy_create_extension.tsx @@ -84,32 +84,33 @@ export const EndpointPolicyCreateExtension = memo { - onChange({ - isValid: false, - updatedPolicy: { - ...newPolicy, - name: '', - inputs: [ - { - enabled: true, - streams: [], - type: ENDPOINT_INTEGRATION_CONFIG_KEY, - config: { - _config: { - value: { - type: 'endpoint', - endpointConfig: { - preset: 'NGAV', + if (initialRender.current) { + onChange({ + isValid: false, + updatedPolicy: { + ...newPolicy, + name: '', + inputs: [ + { + enabled: true, + streams: [], + type: ENDPOINT_INTEGRATION_CONFIG_KEY, + config: { + _config: { + value: { + type: 'endpoint', + endpointConfig: { + preset: 'NGAV', + }, }, }, }, }, - }, - ], - }, - }); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + ], + }, + }); + } + }, [onChange, newPolicy]); useEffect(() => { // Skip trigerring this onChange on the initial render