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

Add vulnerabilities configurations and healthCheck #6147

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions plugins/main/common/config-equivalences.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export const configEquivalences = {
'Define the number of replicas to use for the statistics indices.',
'alerts.sample.prefix':
'Define the index name prefix of sample alerts. It must match the template used by the index pattern to avoid unknown fields in dashboards.',
'vulnerabilities.pattern':
'Default index pattern to use for vulnerabilities.',
};

export const nameEquivalence = {
Expand Down Expand Up @@ -94,20 +96,24 @@ export const nameEquivalence = {
'cron.statistics.index.shards': 'Index shards',
'cron.statistics.index.replicas': 'Index replicas',
'alerts.sample.prefix': 'Sample alerts prefix',
'vulnerabilities.pattern': 'Index pattern',
'checks.vulnerabilities.pattern': 'Vulnerabilities index pattern',
};

const HEALTH_CHECK = 'Health Check';
const GENERAL = 'General';
const SECURITY = 'Security';
const MONITORING = 'Monitoring';
const STATISTICS = 'Statistics';
const VULNERABILITIES = 'Vulnerabilities';
const CUSTOMIZATION = 'Logo Customization';
export const categoriesNames = [
HEALTH_CHECK,
GENERAL,
SECURITY,
MONITORING,
STATISTICS,
VULNERABILITIES,
CUSTOMIZATION,
];

Expand Down Expand Up @@ -145,6 +151,8 @@ export const categoriesEquivalence = {
'cron.statistics.index.shards': STATISTICS,
'cron.statistics.index.replicas': STATISTICS,
'alerts.sample.prefix': GENERAL,
'vulnerabilities.pattern': VULNERABILITIES,
'checks.vulnerabilities.pattern': HEALTH_CHECK,
};

const TEXT = 'text';
Expand Down Expand Up @@ -216,4 +224,6 @@ export const formEquivalence = {
'cron.statistics.index.shards': { type: NUMBER },
'cron.statistics.index.replicas': { type: NUMBER },
'alerts.sample.prefix': { type: TEXT },
'vulnerabilities.pattern': { type: TEXT },
'checks.vulnerabilities.pattern': { type: BOOLEAN },
};
73 changes: 72 additions & 1 deletion plugins/main/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ export const WAZUH_STATISTICS_DEFAULT_STATUS = true;
export const WAZUH_STATISTICS_DEFAULT_FREQUENCY = 900;
export const WAZUH_STATISTICS_DEFAULT_CRON_FREQ = '0 */5 * * * *';

// Wazuh vulnerabilities
export const WAZUH_VULNERABILITIES_PATTERN = 'wazuh-states-vulnerabilities';

// Job - Wazuh initialize
export const WAZUH_PLUGIN_PLATFORM_TEMPLATE_NAME = 'wazuh-kibana';

Expand Down Expand Up @@ -402,6 +405,10 @@ export const ELASTIC_NAME = 'elastic';
// Default Wazuh indexer name
export const WAZUH_INDEXER_NAME = 'Wazuh indexer';

// Not timeFieldName on index pattern
export const NOT_TIME_FIELD_NAME_INDEX_PATTERN =
'not_time_field_name_index_pattern';

// Customization
export const CUSTOMIZATION_ENDPOINT_PAYLOAD_UPLOAD_CUSTOM_FILE_MAXIMUM_BYTES = 1048576;

Expand All @@ -411,6 +418,7 @@ export enum SettingCategory {
HEALTH_CHECK,
MONITORING,
STATISTICS,
VULNERABILITIES,
SECURITY,
CUSTOMIZATION,
}
Expand Down Expand Up @@ -563,6 +571,12 @@ export const PLUGIN_SETTINGS_CATEGORIES: {
'Options related to the daemons manager monitoring job and their storage in indexes.',
renderOrder: SettingCategory.STATISTICS,
},
[SettingCategory.VULNERABILITIES]: {
title: 'Vulnerabilities',
description:
'Options related to the agent vulnerabilities monitoring job and its storage in indexes.',
renderOrder: SettingCategory.VULNERABILITIES,
},
[SettingCategory.CUSTOMIZATION]: {
title: 'Custom branding',
description:
Expand Down Expand Up @@ -820,6 +834,33 @@ export const PLUGIN_SETTINGS: { [key: string]: TPluginSetting } = {
return schema.boolean();
},
},
'checks.vulnerabilities.pattern': {
title: 'Vulnerabilities index pattern',
description:
'Enable or disable the vulnerabilities index pattern health check when opening the app.',
category: SettingCategory.HEALTH_CHECK,
type: EpluginSettingType.switch,
defaultValue: true,
isConfigurableFromFile: true,
isConfigurableFromUI: true,
options: {
switch: {
values: {
disabled: { label: 'false', value: false },
enabled: { label: 'true', value: true },
},
},
},
uiFormTransformChangedInputValue: function (
value: boolean | string,
): boolean {
return Boolean(value);
},
validate: SettingsValidator.isBoolean,
validateBackend: function (schema) {
return schema.boolean();
},
},
'cron.prefix': {
title: 'Cron prefix',
description: 'Define the index prefix of predefined jobs.',
Expand Down Expand Up @@ -1108,7 +1149,7 @@ export const PLUGIN_SETTINGS: { [key: string]: TPluginSetting } = {
},
'customization.logo.app': {
title: 'App main logo',
description: `This logo is used as loading indicator while the user is logging into Wazuh API`,
description: `This logo is used as loading indicator while the user is logging into Wazuh API.`,
category: SettingCategory.CUSTOMIZATION,
type: EpluginSettingType.filepicker,
defaultValue: '',
Expand Down Expand Up @@ -1720,6 +1761,36 @@ export const PLUGIN_SETTINGS: { [key: string]: TPluginSetting } = {
return schema.number({ validate: this.validate.bind(this) });
},
},
'vulnerabilities.pattern': {
title: 'Index pattern',
description: 'Default index pattern to use for vulnerabilities.',
category: SettingCategory.VULNERABILITIES,
type: EpluginSettingType.text,
defaultValue: WAZUH_VULNERABILITIES_PATTERN,
isConfigurableFromFile: true,
isConfigurableFromUI: true,
requiresRunningHealthCheck: false,
validate: SettingsValidator.compose(
SettingsValidator.isNotEmptyString,
SettingsValidator.hasNoSpaces,
SettingsValidator.noLiteralString('.', '..'),
SettingsValidator.noStartsWithString('-', '_', '+', '.'),
SettingsValidator.hasNotInvalidCharacters(
'\\',
'/',
'?',
'"',
'<',
'>',
'|',
',',
'#',
),
),
validateBackend: function (schema) {
return schema.string({ minLength: 1, validate: this.validate });
},
},
};

export type TPluginSettingKey = keyof typeof PLUGIN_SETTINGS;
Expand Down
18 changes: 18 additions & 0 deletions plugins/main/common/plugin-settings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ describe('[settings] Input validation', () => {
${'checks.template'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
${'checks.timeFilter'} | ${true} | ${undefined}
${'checks.timeFilter'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
${'checks.vulnerabilities.pattern'} | ${true} | ${undefined}
${'checks.vulnerabilities.pattern'} | ${0} | ${'It should be a boolean. Allowed values: true or false.'}
${'cron.prefix'} | ${'test'} | ${undefined}
${'cron.prefix'} | ${'test space'} | ${'No whitespaces allowed.'}
${'cron.prefix'} | ${''} | ${'Value can not be empty.'}
Expand Down Expand Up @@ -208,6 +210,22 @@ describe('[settings] Input validation', () => {
${'wazuh.monitoring.shards'} | ${-1} | ${'Value should be greater or equal than 1.'}
${'wazuh.monitoring.shards'} | ${'1.2'} | ${'Number should be an integer.'}
${'wazuh.monitoring.shards'} | ${1.2} | ${'Number should be an integer.'}
${'vulnerabilities.pattern'} | ${'test'} | ${undefined}
${'vulnerabilities.pattern'} | ${'test*'} | ${undefined}
${'vulnerabilities.pattern'} | ${''} | ${'Value can not be empty.'}
${'vulnerabilities.pattern'} | ${'-test'} | ${"It can't start with: -, _, +, .."}
${'vulnerabilities.pattern'} | ${'_test'} | ${"It can't start with: -, _, +, .."}
${'vulnerabilities.pattern'} | ${'+test'} | ${"It can't start with: -, _, +, .."}
${'vulnerabilities.pattern'} | ${'.test'} | ${"It can't start with: -, _, +, .."}
${'vulnerabilities.pattern'} | ${'test\\'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test/'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test?'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test"'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test<'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test>'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test|'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test,'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
${'vulnerabilities.pattern'} | ${'test#'} | ${'It can\'t contain invalid characters: \\, /, ?, ", <, >, |, ,, #.'}
`(
'$setting | $value | $expectedValidation',
({ setting, value, expectedValidation }) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ exports[`Check result component should render a Check result screen 1`] = `
check={true}
checksReady={Object {}}
cleanErrors={[MockFunction]}
cleanWarnings={[MockFunction]}
handleCheckReady={[MockFunction]}
handleErrors={[MockFunction]}
handleWarnings={[MockFunction]}
isLoading={false}
name="test"
title="Check Test"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,15 @@ import { act } from 'react-dom/test-utils';

describe('Check result component', () => {
const validationService = jest.fn();
const handleWarnings = jest.fn();
const handleErrors = jest.fn();
const handleCheckReady = jest.fn();
const cleanWarnings = jest.fn();
const cleanErrors = jest.fn();

const awaitForMyComponent = async (wrapper: any) => {
await act(async () => {
await new Promise((resolve) => setTimeout(resolve, 0));
await new Promise(resolve => setTimeout(resolve, 0));
wrapper.update();
});
};
Expand All @@ -38,13 +40,15 @@ describe('Check result component', () => {
awaitFor={[]}
check={true}
validationService={validationService}
handleWarnings={handleWarnings}
handleErrors={handleErrors}
isLoading={false}
handleCheckReady={handleCheckReady}
checksReady={{}}
cleanWarnings={cleanWarnings}
cleanErrors={cleanErrors}
canRetry={true}
/>
/>,
);

expect(component).toMatchSnapshot();
Expand All @@ -59,13 +63,15 @@ describe('Check result component', () => {
awaitFor={[]}
shouldCheck={true}
validationService={validationService}
handleWarnings={handleWarnings}
handleErrors={handleErrors}
isLoading={false}
handleCheckReady={handleCheckReady}
checksReady={{}}
cleanWarnings={cleanWarnings}
cleanErrors={cleanErrors}
canRetry={true}
/>
/>,
);

await awaitForMyComponent(wrapper);
Expand All @@ -85,13 +91,15 @@ describe('Check result component', () => {
awaitFor={[]}
shouldCheck={true}
validationService={validationService}
handleWarnings={handleWarnings}
handleErrors={handleErrors}
isLoading={false}
handleCheckReady={handleCheckReady}
checksReady={{}}
cleanWarnings={cleanWarnings}
cleanErrors={cleanErrors}
canRetry={true}
/>
/>,
);

await awaitForMyComponent(wrapper);
Expand All @@ -111,13 +119,15 @@ describe('Check result component', () => {
awaitFor={[]}
shouldCheck={true}
validationService={validationService}
handleWarnings={handleWarnings}
handleErrors={handleErrors}
isLoading={false}
handleCheckReady={handleCheckReady}
checksReady={{}}
cleanWarnings={cleanWarnings}
cleanErrors={cleanErrors}
canRetry={false}
/>
/>,
);

expect(wrapper.find('ResultIcons').exists()).toBeTruthy();
Expand Down
Loading
Loading