Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Security Solution] Add linux malware config options and migration #100166

Merged
merged 12 commits into from
May 19, 2021
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,14 @@ import { migrateEndpointPackagePolicyToV7140 } from './to_v7_14_0';

describe('7.14.0 Endpoint Package Policy migration', () => {
const migration = migrateEndpointPackagePolicyToV7140;
it('adds supported option for ransomware on migrations', () => {
const doc = {
const policyDoc = ({
windowsMalware = {},
windowsRansomware = {},
windowsPopup = {},
linuxMalware = {},
linuxPopup = {},
}) => {
return {
id: 'mock-saved-object-id',
attributes: {
name: 'Some Policy Name',
Expand Down Expand Up @@ -42,26 +48,15 @@ describe('7.14.0 Endpoint Package Policy migration', () => {
policy: {
value: {
windows: {
ransomware: {
mode: 'off',
},
malware: {
mode: 'off',
},
popup: {
malware: {
message: '',
enabled: false,
},
ransomware: {
message: '',
enabled: false,
},
},
...windowsMalware,
...windowsRansomware,
...windowsPopup,
},
linux: {
events: { process: true, file: true, network: true },
logging: { file: 'info' },
...linuxMalware,
...linuxPopup,
},
},
},
Expand All @@ -71,65 +66,108 @@ describe('7.14.0 Endpoint Package Policy migration', () => {
},
type: ' nested',
};
};

expect(migration(doc, {} as SavedObjectMigrationContext)).toEqual({
attributes: {
name: 'Some Policy Name',
package: {
name: 'endpoint',
title: '',
version: '',
it('adds supported option for ransomware on migrations and linux malware when windows malware is disabled', () => {
const initialDoc = policyDoc({
windowsMalware: { malware: { mode: 'off' } },
windowsRansomware: { ransomware: { mode: 'off' } },
windowsPopup: {
popup: {
malware: {
message: '',
enabled: false,
},
ransomware: {
message: '',
enabled: false,
},
},
id: 'endpoint',
policy_id: '',
enabled: true,
namespace: '',
output_id: '',
revision: 0,
updated_at: '',
updated_by: '',
created_at: '',
created_by: '',
inputs: [
{
type: 'endpoint',
},
});

const migratedDoc = policyDoc({
windowsMalware: { malware: { mode: 'off' } },
windowsRansomware: { ransomware: { mode: 'off', supported: true } },
windowsPopup: {
popup: {
malware: {
message: '',
enabled: false,
},
ransomware: {
message: '',
enabled: false,
},
},
},
linuxMalware: {
malware: {
mode: 'off',
},
},
linuxPopup: {
popup: {
malware: {
message: '',
enabled: false,
},
},
},
});

expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
});

it('adds supported option for ransomware on migrations and linux malware option and notification customization when windows malware is enabled', () => {
const initialDoc = policyDoc({
windowsMalware: { malware: { mode: 'on' } },
windowsRansomware: { ransomware: { mode: 'on' } },
windowsPopup: {
popup: {
malware: {
message: '',
enabled: true,
streams: [],
config: {
policy: {
value: {
windows: {
ransomware: {
mode: 'off',
supported: true,
},
malware: {
mode: 'off',
},
popup: {
malware: {
message: '',
enabled: false,
},
ransomware: {
message: '',
enabled: false,
},
},
},
linux: {
events: { process: true, file: true, network: true },
logging: { file: 'info' },
},
},
},
},
},
],
ransomware: {
message: '',
enabled: true,
},
},
},
type: ' nested',
id: 'mock-saved-object-id',
});

const migratedDoc = policyDoc({
windowsMalware: { malware: { mode: 'on' } },
windowsRansomware: { ransomware: { mode: 'on', supported: true } },
windowsPopup: {
popup: {
malware: {
message: '',
enabled: true,
},
ransomware: {
message: '',
enabled: true,
},
},
},
linuxMalware: {
malware: {
mode: 'on',
},
},
linuxPopup: {
popup: {
malware: {
message: '',
enabled: true,
},
},
},
});

expect(migration(initialDoc, {} as SavedObjectMigrationContext)).toEqual(migratedDoc);
});

it('does not modify non-endpoint package policies', () => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,17 @@ export const migrateEndpointPackagePolicyToV7140: SavedObjectMigrationFn<
const updatedPackagePolicyDoc: SavedObjectUnsanitizedDoc<PackagePolicy> = cloneDeep(
packagePolicyDoc
);

if (packagePolicyDoc.attributes.package?.name === 'endpoint') {
const input = updatedPackagePolicyDoc.attributes.inputs[0];
if (input && input.config) {
const policy = input.config.policy.value;
const linuxMalware = cloneDeep(input.config.policy.value.windows.malware);
const linuxMalwarePopup = {
malware: cloneDeep(input.config.policy.value.windows.popup.malware),
};

policy.linux.malware = linuxMalware;
policy.linux.popup = linuxMalwarePopup;

// This value is based on license.
// For the migration, we add 'true', our license watcher will correct it, if needed, when the app starts.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,15 @@ export const policyFactory = (): PolicyConfig => {
file: true,
network: true,
},
malware: {
mode: ProtectionModes.prevent,
},
popup: {
malware: {
message: '',
enabled: true,
},
},
logging: {
file: 'info',
},
Expand Down Expand Up @@ -114,6 +123,16 @@ export const policyFactoryWithoutPaidFeatures = (
},
},
},
linux: {
...policy.linux,
popup: {
...policy.linux.popup,
malware: {
message: '',
enabled: true,
},
},
},
};
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -878,6 +878,13 @@ export interface PolicyConfig {
process: boolean;
network: boolean;
};
malware: ProtectionFields;
popup: {
malware: {
message: string;
enabled: boolean;
};
};
logging: {
file: string;
};
Expand All @@ -902,7 +909,7 @@ export interface UIPolicyConfig {
/**
* Linux-specific policy configuration that is supported via the UI
*/
linux: Pick<PolicyConfig['linux'], 'events' | 'advanced'>;
linux: Pick<PolicyConfig['linux'], 'malware' | 'events' | 'popup' | 'advanced'>;
}

/** Policy: Protection fields */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,13 @@ describe('policy details: ', () => {
linux: {
events: { process: true, file: true, network: true },
logging: { file: 'info' },
malware: { mode: 'prevent' },
popup: {
malware: {
enabled: true,
message: '',
},
},
},
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ export const policyDetailsMiddlewareFactory: ImmutableMiddlewareFactory<PolicyDe
if (policyItem.inputs[0].config.policy.value.windows.popup.malware.message === '') {
policyItem.inputs[0].config.policy.value.windows.popup.malware.message = DefaultMalwareMessage;
policyItem.inputs[0].config.policy.value.mac.popup.malware.message = DefaultMalwareMessage;
policyItem.inputs[0].config.policy.value.linux.popup.malware.message = DefaultMalwareMessage;
}
if (policyItem.inputs[0].config.policy.value.windows.popup.ransomware.message === '') {
policyItem.inputs[0].config.policy.value.windows.popup.ransomware.message = DefaultMalwareMessage;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,8 @@ export const policyConfig: (s: PolicyDetailsState) => UIPolicyConfig = createSel
linux: {
advanced: linux.advanced,
events: linux.events,
malware: linux.malware,
popup: linux.popup,
},
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,10 +122,13 @@ export type RansomwareProtectionOSes = KeysByValueCriteria<

export type PolicyProtection =
| keyof Pick<UIPolicyConfig['windows'], 'malware' | 'ransomware'>
| keyof Pick<UIPolicyConfig['mac'], 'malware'>;
| keyof Pick<UIPolicyConfig['mac'], 'malware'>
| keyof Pick<UIPolicyConfig['linux'], 'malware'>;

export type MacPolicyProtection = keyof Pick<UIPolicyConfig['mac'], 'malware'>;

export type LinuxPolicyProtection = keyof Pick<UIPolicyConfig['linux'], 'malware'>;

export interface GetPolicyListResponse extends GetPackagePoliciesResponse {
items: PolicyData[];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
ProtectionModes,
UIPolicyConfig,
} from '../../../../../../../common/endpoint/types';
import { MacPolicyProtection, PolicyProtection } from '../../../types';
import { MacPolicyProtection, LinuxPolicyProtection, PolicyProtection } from '../../../types';
import { usePolicyDetailsSelector } from '../../policy_hooks';
import { policyConfig } from '../../../store/policy_details/selectors';
import { AppAction } from '../../../../../../common/store/actions';
Expand Down Expand Up @@ -46,6 +46,8 @@ export const ProtectionRadio = React.memo(
newPayload[os][protection].mode = protectionMode;
} else if (os === 'mac') {
newPayload[os][protection as MacPolicyProtection].mode = protectionMode;
} else if (os === 'linux') {
newPayload[os][protection as LinuxPolicyProtection].mode = protectionMode;
}
if (isPlatinumPlus) {
if (os === 'windows') {
Expand All @@ -60,6 +62,12 @@ export const ProtectionRadio = React.memo(
} else {
newPayload[os].popup[protection as MacPolicyProtection].enabled = false;
}
} else if (os === 'linux') {
if (protectionMode === ProtectionModes.prevent) {
newPayload[os].popup[protection as LinuxPolicyProtection].enabled = true;
} else {
newPayload[os].popup[protection as LinuxPolicyProtection].enabled = false;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
ProtectionModes,
UIPolicyConfig,
} from '../../../../../../../common/endpoint/types';
import { PolicyProtection, MacPolicyProtection } from '../../../types';
import { PolicyProtection, MacPolicyProtection, LinuxPolicyProtection } from '../../../types';
import { ConfigFormHeading } from '../../components/config_form';
import { usePolicyDetailsSelector } from '../../policy_hooks';
import { policyConfig } from '../../../store/policy_details/selectors';
Expand Down Expand Up @@ -57,6 +57,9 @@ export const UserNotification = React.memo(
} else if (os === 'mac') {
newPayload[os].popup[protection as MacPolicyProtection].enabled =
event.target.checked;
} else if (os === 'linux') {
newPayload[os].popup[protection as LinuxPolicyProtection].enabled =
event.target.checked;
}
}
dispatch({
Expand All @@ -77,6 +80,9 @@ export const UserNotification = React.memo(
newPayload[os].popup[protection].message = event.target.value;
} else if (os === 'mac') {
newPayload[os].popup[protection as MacPolicyProtection].message = event.target.value;
} else if (os === 'linux') {
newPayload[os].popup[protection as LinuxPolicyProtection].message =
event.target.value;
}
}
dispatch({
Expand Down
Loading