Skip to content

Commit

Permalink
[Security Solution] Session Data eventing switch in Linux Endpoint po…
Browse files Browse the repository at this point in the history
…licy (#128149)
  • Loading branch information
kevinlog authored Mar 28, 2022
1 parent 6ef78e6 commit 9655416
Show file tree
Hide file tree
Showing 8 changed files with 164 additions and 45 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,12 @@ import type { PackagePolicy } from '../../../../common';
import { migratePackagePolicyToV820 as migration } from './to_v8_2_0';

describe('8.2.0 Endpoint Package Policy migration', () => {
const policyDoc = ({ windowsMalware = {}, macMalware = {}, linuxMalware = {} }) => {
const policyDoc = ({
windowsMalware = {},
macMalware = {},
linuxMalware = {},
linuxEvents = {},
}) => {
return {
id: 'mock-saved-object-id',
attributes: {
Expand Down Expand Up @@ -48,6 +53,7 @@ describe('8.2.0 Endpoint Package Policy migration', () => {
},
linux: {
...linuxMalware,
...linuxEvents,
},
},
},
Expand All @@ -64,12 +70,14 @@ describe('8.2.0 Endpoint Package Policy migration', () => {
windowsMalware: { malware: { mode: 'off' } },
macMalware: { malware: { mode: 'off' } },
linuxMalware: { malware: { mode: 'off' } },
linuxEvents: { events: { process: true, file: true, network: true } },
});

const migratedDoc = policyDoc({
windowsMalware: { malware: { mode: 'off', blocklist: false } },
macMalware: { malware: { mode: 'off', blocklist: false } },
linuxMalware: { malware: { mode: 'off', blocklist: false } },
linuxEvents: { events: { process: true, file: true, network: true, session_data: false } },
});

expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
Expand All @@ -80,12 +88,14 @@ describe('8.2.0 Endpoint Package Policy migration', () => {
windowsMalware: { malware: { mode: 'prevent' } },
macMalware: { malware: { mode: 'prevent' } },
linuxMalware: { malware: { mode: 'prevent' } },
linuxEvents: { events: { process: true, file: true, network: true } },
});

const migratedDoc = policyDoc({
windowsMalware: { malware: { mode: 'prevent', blocklist: true } },
macMalware: { malware: { mode: 'prevent', blocklist: true } },
linuxMalware: { malware: { mode: 'prevent', blocklist: true } },
linuxEvents: { events: { process: true, file: true, network: true, session_data: false } },
});

expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
Expand All @@ -96,12 +106,14 @@ describe('8.2.0 Endpoint Package Policy migration', () => {
windowsMalware: { malware: { mode: 'detect' } },
macMalware: { malware: { mode: 'detect' } },
linuxMalware: { malware: { mode: 'detect' } },
linuxEvents: { events: { process: true, file: true, network: true } },
});

const migratedDoc = policyDoc({
windowsMalware: { malware: { mode: 'detect', blocklist: true } },
macMalware: { malware: { mode: 'detect', blocklist: true } },
linuxMalware: { malware: { mode: 'detect', blocklist: true } },
linuxEvents: { events: { process: true, file: true, network: true, session_data: false } },
});

expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ export const migratePackagePolicyToV820: SavedObjectMigrationFn<PackagePolicy, P
policy.windows.malware.blocklist = policy.windows.malware.mode !== 'off';
policy.mac.malware.blocklist = policy.mac.malware.mode !== 'off';
policy.linux.malware.blocklist = policy.linux.malware.mode !== 'off';

policy.linux.events.session_data = false;
}

return updatedPackagePolicyDoc;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export const policyFactory = (): PolicyConfig => {
process: true,
file: true,
network: true,
session_data: false,
},
malware: {
mode: ProtectionModes.prevent,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,7 @@ export interface PolicyConfig {
file: boolean;
process: boolean;
network: boolean;
session_data: boolean;
};
malware: ProtectionFields & BlocklistFields;
behavior_protection: ProtectionFields & SupportedFields;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -873,4 +873,15 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [
}
),
},
{
key: 'linux.advanced.kernel.capture_mode',
first_supported_version: '8.2',
documentation: i18n.translate(
'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.kernel.capture_mode',
{
defaultMessage:
'Allows users to control whether kprobes or ebpf are used to gather data. Possible options are kprobes, ebpf, or auto. Default: auto',
}
),
},
];
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ describe('policy details: ', () => {
logging: { file: 'info' },
},
linux: {
events: { process: true, file: true, network: true },
events: { process: true, file: true, network: true, session_data: false },
logging: { file: 'info' },
malware: { mode: 'prevent', blocklist: true },
behavior_protection: { mode: 'off', supported: false },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,21 @@
* 2.0.
*/

import React from 'react';
import React, { useContext, useCallback } from 'react';
import { i18n } from '@kbn/i18n';
import { EuiCheckbox, EuiSpacer, EuiText, htmlIdGenerator } from '@elastic/eui';
import {
EuiCheckbox,
EuiSpacer,
EuiText,
htmlIdGenerator,
EuiSwitch,
EuiIconTip,
EuiBetaBadge,
EuiFlexItem,
EuiFlexGroup,
} from '@elastic/eui';
import { OperatingSystem } from '@kbn/securitysolution-utils';
import { ThemeContext } from 'styled-components';
import { PolicyOperatingSystem, UIPolicyConfig } from '../../../../../../../common/endpoint/types';
import { ConfigForm, ConfigFormHeading } from '../../components/config_form';

Expand All @@ -34,54 +45,110 @@ export interface EventFormOption<T extends OperatingSystem> {
protectionField: ProtectionField<T>;
}

export interface SupplementalEventFormOption<T extends OperatingSystem> {
name: string;
protectionField: ProtectionField<T>;
tooltipText?: string;
beta?: boolean;
}

export interface EventsFormProps<T extends OperatingSystem> {
os: T;
options: ReadonlyArray<EventFormOption<T>>;
selection: EventFormSelection<T>;
onValueSelection: (value: ProtectionField<T>, selected: boolean) => void;
supplementalOptions?: ReadonlyArray<SupplementalEventFormOption<T>>;
}

const countSelected = <T extends OperatingSystem>(selection: EventFormSelection<T>) => {
return Object.values(selection).filter((value) => value).length;
};

export const EventsForm = <T extends OperatingSystem>({
const InnerEventsForm = <T extends OperatingSystem>({
os,
options,
selection,
onValueSelection,
}: EventsFormProps<T>) => (
<ConfigForm
type={i18n.translate('xpack.securitySolution.endpoint.policy.details.eventCollection', {
defaultMessage: 'Event collection',
})}
supportedOss={[os]}
rightCorner={
<EuiText size="s" color="subdued">
{i18n.translate('xpack.securitySolution.endpoint.policy.details.eventCollectionsEnabled', {
defaultMessage: '{selected} / {total} event collections enabled',
values: { selected: countSelected(selection), total: options.length },
supplementalOptions,
}: EventsFormProps<T>) => {
const theme = useContext(ThemeContext);
const countSelected = useCallback(() => {
const supplementalSelectionFields: string[] = supplementalOptions
? supplementalOptions.map((value) => value.protectionField as string)
: [];
return Object.entries(selection).filter(([key, value]) =>
!supplementalSelectionFields.includes(key) ? value : false
).length;
}, [selection, supplementalOptions]);

return (
<ConfigForm
type={i18n.translate('xpack.securitySolution.endpoint.policy.details.eventCollection', {
defaultMessage: 'Event collection',
})}
supportedOss={[os]}
rightCorner={
<EuiText size="s" color="subdued">
{i18n.translate(
'xpack.securitySolution.endpoint.policy.details.eventCollectionsEnabled',
{
defaultMessage: '{selected} / {total} event collections enabled',
values: {
selected: countSelected(),
total: options.length,
},
}
)}
</EuiText>
}
>
<ConfigFormHeading>
{i18n.translate('xpack.securitySolution.endpoint.policyDetailsConfig.eventingEvents', {
defaultMessage: 'Events',
})}
</EuiText>
}
>
<ConfigFormHeading>
{i18n.translate('xpack.securitySolution.endpoint.policyDetailsConfig.eventingEvents', {
defaultMessage: 'Events',
</ConfigFormHeading>
<EuiSpacer size="s" />
{options.map(({ name, protectionField }) => {
return (
<EuiCheckbox
key={String(protectionField)}
id={htmlIdGenerator()()}
label={name}
data-test-subj={`policy${OPERATING_SYSTEM_TO_TEST_SUBJ[os]}Event_${protectionField}`}
checked={selection[protectionField]}
onChange={(event) => onValueSelection(protectionField, event.target.checked)}
/>
);
})}
</ConfigFormHeading>
<EuiSpacer size="s" />
{options.map(({ name, protectionField }) => (
<EuiCheckbox
key={String(protectionField)}
id={htmlIdGenerator()()}
label={name}
data-test-subj={`policy${OPERATING_SYSTEM_TO_TEST_SUBJ[os]}Event_${protectionField}`}
checked={selection[protectionField]}
onChange={(event) => onValueSelection(protectionField, event.target.checked)}
/>
))}
</ConfigForm>
);
{supplementalOptions &&
supplementalOptions.map(({ name, protectionField, tooltipText, beta }) => {
return (
<div key={String(protectionField)} style={{ paddingLeft: theme.eui.paddingSizes.s }}>
<EuiFlexGroup direction="row" gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiSpacer size="s" />
<EuiSwitch
id={htmlIdGenerator()()}
label={name}
data-test-subj={`policy${OPERATING_SYSTEM_TO_TEST_SUBJ[os]}Event_${protectionField}`}
checked={selection[protectionField]}
onChange={(event) => onValueSelection(protectionField, event.target.checked)}
/>
</EuiFlexItem>
{tooltipText && (
<EuiFlexItem grow={false}>
<EuiIconTip position="right" content={tooltipText} />
</EuiFlexItem>
)}
{beta && (
<EuiFlexItem grow={false}>
<EuiBetaBadge label="beta" size="s" />
</EuiFlexItem>
)}
</EuiFlexGroup>
</div>
);
})}
</ConfigForm>
);
};

InnerEventsForm.displayName = 'EventsForm';

EventsForm.displayName = 'EventsForm';
export const EventsForm = React.memo(InnerEventsForm) as typeof InnerEventsForm;
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,11 @@ import { OperatingSystem } from '@kbn/securitysolution-utils';
import { policyConfig } from '../../../store/policy_details/selectors';
import { setIn } from '../../../models/policy_details_config';
import { usePolicyDetailsSelector } from '../../policy_hooks';
import { EventFormOption, EventsForm } from '../../components/events_form';
import {
EventFormOption,
EventsForm,
SupplementalEventFormOption,
} from '../../components/events_form';

const OPTIONS: ReadonlyArray<EventFormOption<OperatingSystem.LINUX>> = [
{
Expand All @@ -21,6 +25,15 @@ const OPTIONS: ReadonlyArray<EventFormOption<OperatingSystem.LINUX>> = [
}),
protectionField: 'file',
},
{
name: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.network',
{
defaultMessage: 'Network',
}
),
protectionField: 'network',
},
{
name: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.process',
Expand All @@ -30,14 +43,25 @@ const OPTIONS: ReadonlyArray<EventFormOption<OperatingSystem.LINUX>> = [
),
protectionField: 'process',
},
];

const SUPPLEMENTAL_OPTIONS: ReadonlyArray<SupplementalEventFormOption<OperatingSystem.LINUX>> = [
{
name: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.network',
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data',
{
defaultMessage: 'Network',
defaultMessage: 'Include session data',
}
),
protectionField: 'network',
protectionField: 'session_data',
tooltipText: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.tooltip',
{
defaultMessage:
'Capture the extended process event data required for Session View. Session View helps you investigate process, user, and service activity on your Linux infrastructure by displaying session and process execution data organized in a tree according to the Linux process model. NOTE: Capturing extended process events substantially increases data usage.',
}
),
beta: true,
},
];

Expand All @@ -50,6 +74,7 @@ export const LinuxEvents = memo(() => {
os={OperatingSystem.LINUX}
selection={policyDetailsConfig.linux.events}
options={OPTIONS}
supplementalOptions={SUPPLEMENTAL_OPTIONS}
onValueSelection={(value, selected) =>
dispatch({
type: 'userChangedPolicyConfig',
Expand Down

0 comments on commit 9655416

Please sign in to comment.