[Terminal Output] Config options added to policy (#139421)

* [Terminal Output] Config options added to policy

reverted test mocks for tty events

[CI] Auto-commit changed files from 'node scripts/precommit_hook.js --ref HEAD~1..HEAD --fix'

copy updates

removed unused translations

* change reverted

* fixed type error

Co-authored-by: Karl Godard <karlgodard@elastic.co>
This commit is contained in:
Karl Godard 2022-08-29 13:31:35 -07:00 committed by GitHub
parent 1ebfd79daf
commit d2ea8bf58f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
12 changed files with 328 additions and 40 deletions

View file

@ -14,3 +14,4 @@ export { migratePackagePolicyToV7160 } from './to_v7_16_0';
export { migratePackagePolicyToV820 } from './to_v8_2_0';
export { migratePackagePolicyToV830 } from './to_v8_3_0';
export { migratePackagePolicyToV840 } from './to_v8_4_0';
export { migratePackagePolicyToV850 } from './to_v8_5_0';

View file

@ -0,0 +1,144 @@
/*
* 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 { SavedObjectMigrationContext, SavedObjectUnsanitizedDoc } from '@kbn/core/server';
import type { PackagePolicy } from '../../../../common';
import { migratePackagePolicyToV850 as migration } from './to_v8_5_0';
describe('8.5.0 Endpoint Package Policy migration', () => {
const policyDoc = ({
windowsMalware = {},
macMalware = {},
linuxMalware = {},
linuxEvents = {},
}) => {
return {
id: 'mock-saved-object-id',
attributes: {
name: 'Some Policy Name',
package: {
name: 'endpoint',
title: '',
version: '',
},
id: 'endpoint',
policy_id: '',
enabled: true,
namespace: '',
revision: 0,
updated_at: '',
updated_by: '',
created_at: '',
created_by: '',
inputs: [
{
type: 'endpoint',
enabled: true,
streams: [],
config: {
policy: {
value: {
windows: {
...windowsMalware,
},
mac: {
...macMalware,
},
linux: {
...linuxMalware,
...linuxEvents,
},
},
},
},
},
],
},
type: ' nested',
};
};
it('adds tty_io defaulted to false', () => {
const initialDoc = policyDoc({
linuxEvents: { events: { process: true, file: true, network: true } },
});
const migratedDoc = policyDoc({
linuxEvents: {
events: { process: true, file: true, network: true, tty_io: false },
},
});
expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
});
it('does not modify non-endpoint package policies', () => {
const doc: SavedObjectUnsanitizedDoc<PackagePolicy> = {
id: 'mock-saved-object-id',
attributes: {
name: 'Some Policy Name',
package: {
name: 'notEndpoint',
title: '',
version: '',
},
id: 'notEndpoint',
policy_id: '',
enabled: true,
namespace: '',
revision: 0,
updated_at: '',
updated_by: '',
created_at: '',
created_by: '',
inputs: [
{
type: 'notEndpoint',
enabled: true,
streams: [],
config: {},
},
],
},
type: ' nested',
};
expect(
migration(doc, {} as SavedObjectMigrationContext) as SavedObjectUnsanitizedDoc<PackagePolicy>
).toEqual({
attributes: {
name: 'Some Policy Name',
package: {
name: 'notEndpoint',
title: '',
version: '',
},
id: 'notEndpoint',
policy_id: '',
enabled: true,
namespace: '',
revision: 0,
updated_at: '',
updated_by: '',
created_at: '',
created_by: '',
inputs: [
{
type: 'notEndpoint',
enabled: true,
streams: [],
config: {},
},
],
},
type: ' nested',
id: 'mock-saved-object-id',
});
});
});

View file

@ -0,0 +1,32 @@
/*
* 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 { SavedObjectMigrationFn, SavedObjectUnsanitizedDoc } from '@kbn/core/server';
import { cloneDeep } from 'lodash';
import type { PackagePolicy } from '../../../../common';
export const migratePackagePolicyToV850: SavedObjectMigrationFn<PackagePolicy, PackagePolicy> = (
packagePolicyDoc
) => {
if (packagePolicyDoc.attributes.package?.name !== 'endpoint') {
return packagePolicyDoc;
}
const updatedPackagePolicyDoc: SavedObjectUnsanitizedDoc<PackagePolicy> =
cloneDeep(packagePolicyDoc);
const input = updatedPackagePolicyDoc.attributes.inputs[0];
if (input && input.config) {
const policy = input.config.policy.value;
policy.linux.events.tty_io = false;
}
return updatedPackagePolicyDoc;
};

View file

@ -111,6 +111,7 @@ export const policyFactory = (): PolicyConfig => {
file: true,
network: true,
session_data: false,
tty_io: false,
},
malware: {
mode: ProtectionModes.prevent,

View file

@ -1007,6 +1007,7 @@ export interface PolicyConfig {
process: boolean;
network: boolean;
session_data: boolean;
tty_io: boolean;
};
malware: ProtectionFields & BlocklistFields;
behavior_protection: ProtectionFields & SupportedFields;

View file

@ -145,6 +145,39 @@ export const AdvancedPolicySchema: AdvancedPolicySchemaType[] = [
}
),
},
{
key: 'linux.advanced.tty_io.max_kilobytes_per_process',
first_supported_version: '8.5',
documentation: i18n.translate(
'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.tty_io.max_kilobytes_per_process',
{
defaultMessage:
'The maximum kilobytes of terminal output to record for a single process. Default: 512',
}
),
},
{
key: 'linux.advanced.tty_io.max_kilobytes_per_event',
first_supported_version: '8.5',
documentation: i18n.translate(
'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.tty_io.max_kilobytes_per_event',
{
defaultMessage:
'The maximum kilobytes of terminal output to record in a single event. Default: 512',
}
),
},
{
key: 'linux.advanced.tty_io.max_event_interval_seconds',
first_supported_version: '8.5',
documentation: i18n.translate(
'xpack.securitySolution.endpoint.policy.advanced.linux.advanced.tty_io.max_event_interval_seconds',
{
defaultMessage:
'The maximum amount of time (seconds) to batch terminal output in a single event. Default: 30',
}
),
},
{
key: 'mac.advanced.agent.connection_delay',
first_supported_version: '7.9',

View file

@ -333,7 +333,13 @@ describe('policy details: ', () => {
logging: { file: 'info' },
},
linux: {
events: { process: true, file: true, network: true, session_data: false },
events: {
process: true,
file: true,
network: true,
session_data: false,
tty_io: false,
},
logging: { file: 'info' },
malware: { mode: 'prevent', blocklist: true },
behavior_protection: { mode: 'off', supported: false },

View file

@ -12,7 +12,6 @@ import {
EuiSpacer,
EuiText,
htmlIdGenerator,
EuiSwitch,
EuiIconTip,
EuiBetaBadge,
EuiFlexItem,
@ -24,6 +23,8 @@ import type {
PolicyOperatingSystem,
UIPolicyConfig,
} from '../../../../../../../common/endpoint/types';
import { usePolicyDetailsSelector } from '../../policy_hooks';
import { policyConfig } from '../../../store/policy_details/selectors';
import { ConfigForm, ConfigFormHeading } from '../config_form';
const OPERATING_SYSTEM_TO_TEST_SUBJ: { [K in OperatingSystem]: string } = {
@ -49,10 +50,14 @@ export interface EventFormOption<T extends OperatingSystem> {
}
export interface SupplementalEventFormOption<T extends OperatingSystem> {
title?: string;
description?: string;
name: string;
protectionField: ProtectionField<T>;
tooltipText?: string;
beta?: boolean;
indented?: boolean;
isDisabled?(policyConfig: UIPolicyConfig): boolean;
}
export interface EventsFormProps<T extends OperatingSystem> {
@ -70,6 +75,7 @@ const InnerEventsForm = <T extends OperatingSystem>({
onValueSelection,
supplementalOptions,
}: EventsFormProps<T>) => {
const policyDetailsConfig = usePolicyDetailsSelector(policyConfig);
const theme = useContext(ThemeContext);
const countSelected = useCallback(() => {
const supplementalSelectionFields: string[] = supplementalOptions
@ -120,34 +126,63 @@ const InnerEventsForm = <T extends OperatingSystem>({
);
})}
{supplementalOptions &&
supplementalOptions.map(({ name, protectionField, tooltipText, beta }) => {
return (
<div key={String(protectionField)} style={{ paddingLeft: theme.eui.euiSizeS }}>
<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>
supplementalOptions.map(
({
title,
description,
name,
protectionField,
tooltipText,
beta,
indented,
isDisabled,
}) => {
return (
<div
key={String(protectionField)}
style={indented ? { paddingLeft: theme.eui.euiSizeL } : {}}
>
{title && (
<>
<EuiSpacer size="m" />
<ConfigFormHeading>{title}</ConfigFormHeading>
</>
)}
{beta && (
<EuiFlexItem grow={false}>
<EuiBetaBadge label="beta" size="s" />
</EuiFlexItem>
{description && (
<>
<EuiSpacer size="s" />
<EuiText size="xs" color="subdued">
{description}
</EuiText>
</>
)}
</EuiFlexGroup>
</div>
);
})}
<EuiFlexGroup direction="row" gutterSize="xs" alignItems="center">
<EuiFlexItem grow={false}>
<EuiSpacer size="s" />
<EuiCheckbox
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)}
disabled={isDisabled ? isDisabled(policyDetailsConfig) : false}
/>
</EuiFlexItem>
{tooltipText && (
<EuiFlexItem grow={false}>
<EuiIconTip position="right" content={tooltipText} />
</EuiFlexItem>
)}
{beta && (
<EuiFlexItem grow={false}>
<EuiBetaBadge label="beta" size="s" />
</EuiFlexItem>
)}
</EuiFlexGroup>
</div>
);
}
)}
</ConfigForm>
);
};

View file

@ -14,6 +14,7 @@ import { setIn } from '../../../models/policy_details_config';
import { usePolicyDetailsSelector } from '../../policy_hooks';
import type { EventFormOption, SupplementalEventFormOption } from '../../components/events_form';
import { EventsForm } from '../../components/events_form';
import type { UIPolicyConfig } from '../../../../../../../common/endpoint/types';
const OPTIONS: ReadonlyArray<EventFormOption<OperatingSystem.LINUX>> = [
{
@ -44,20 +45,49 @@ const OPTIONS: ReadonlyArray<EventFormOption<OperatingSystem.LINUX>> = [
const SUPPLEMENTAL_OPTIONS: ReadonlyArray<SupplementalEventFormOption<OperatingSystem.LINUX>> = [
{
title: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.title',
{
defaultMessage: 'Session data',
}
),
description: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.description',
{
defaultMessage:
'Turn this on to capture the extended process data required for Session View. Session View provides you a visual representation of session and process execution data. Session View data is organized according to the Linux process model to help you investigate process, user, and service activity on your Linux infrastructure.',
}
),
name: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data',
{
defaultMessage: 'Include session data',
defaultMessage: 'Collect session data',
}
),
protectionField: 'session_data',
tooltipText: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.tooltip',
isDisabled: (config: UIPolicyConfig) => {
return !config.linux.events.process;
},
},
{
name: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.tty_io',
{
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.',
defaultMessage: 'Capture terminal output',
}
),
protectionField: 'tty_io',
tooltipText: i18n.translate(
'xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.tty_io.tooltip',
{
defaultMessage:
'Turn this on to collect terminal (tty) output. Terminal output appears in Session View, and you can view it separately to see what commands were executed and how they were typed, provided the terminal is in echo mode.',
}
),
indented: true,
isDisabled: (config: UIPolicyConfig) => {
return !config.linux.events.session_data;
},
beta: true,
},
];
@ -72,12 +102,20 @@ export const LinuxEvents = memo(() => {
selection={policyDetailsConfig.linux.events}
options={OPTIONS}
supplementalOptions={SUPPLEMENTAL_OPTIONS}
onValueSelection={(value, selected) =>
onValueSelection={(value, selected) => {
let newConfig = setIn(policyDetailsConfig)('linux')('events')(value)(selected);
if (value === 'session_data' && !selected) {
newConfig = setIn(newConfig)('linux')('events')('tty_io')(false);
}
dispatch({
type: 'userChangedPolicyConfig',
payload: { policyConfig: setIn(policyDetailsConfig)('linux')('events')(value)(selected) },
})
}
payload: {
policyConfig: newConfig,
},
});
}}
/>
);
});

View file

@ -27804,7 +27804,6 @@
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.network": "Réseau",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.process": "Processus",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data": "Inclure les données de session",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.tooltip": "Capturez les données d'événement de processus étendues requises pour la vue de session. La vue de session vous aide à examiner l'activité des processus, des utilisateurs et des services dans votre infrastructure Linux en affichant les données d'exécution de session et de processus organisées dans une arborescence respectant le modèle de processus Linux. REMARQUE : La capture d'événements de processus étendus augmente considérablement l'utilisation des données.",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.file": "Fichier",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.network": "Réseau",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.process": "Processus",

View file

@ -27781,7 +27781,6 @@
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.network": "ネットワーク",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.process": "プロセス",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data": "セッションデータを含める",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.tooltip": "セッションビューに必要な拡張プロセスイベントデータを取り込みます。セッションビューでは、Linuxプロセスモデルに従い、セッションおよびプロセス実行データをツリービューに整理することで、Linuxインフラストラクチャーのプロセス、ユーザー、サービスアクティビティを調査できます。注拡張されたプロセスイベントを取り込むと、データ使用量が大幅に増加します。",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.file": "ファイル",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.network": "ネットワーク",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.process": "プロセス",

View file

@ -27812,7 +27812,6 @@
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.network": "网络",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.process": "进程",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data": "包括会话数据",
"xpack.securitySolution.endpoint.policyDetailsConfig.linux.events.session_data.tooltip": "捕获会话视图所需的扩展进程事件数据。会话视图将根据 Linux 进程模型显示树形结构的会话和进程执行数据,帮助您调查 Linux 基础架构上的进程、用户和服务活动。注意:捕获扩展进程事件会显著增加数据使用。",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.file": "文件",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.network": "网络",
"xpack.securitySolution.endpoint.policyDetailsConfig.mac.events.process": "进程",