From 7f186d6ac0b292e214e80f2cf4f26e7307f66241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 8 Nov 2024 09:34:48 +0100 Subject: [PATCH 01/30] feat(initialization): add initialization service - Add initialization service - Migrate frontend healthcheck tasks to run in the backend side through the initialization service - Check existence of index pattern: alerts - Check existence of index pattern: monitoring - Check existence of index pattern: statistics - Check existence of index pattern: vulnerabilities-states - Check defined template for alerts index pattern - Check Wazuh dashboard setting: metaFields - Check Wazuh dashboard setting: timeline:max_buckets - Check Wazuh dashboard setting: timepicker:timeDefaults - Check connection-compatibility with Wazuh server APIs --- .../lib/initialization/index-patterns.ts | 161 ++++++++++++++++++ .../main/server/lib/initialization/index.ts | 3 + .../server/lib/initialization/settings.ts | 146 ++++++++++++++++ .../lib/initialization/templates.test.ts | 43 +++++ .../server/lib/initialization/templates.ts | 88 ++++++++++ plugins/main/server/plugin.ts | 123 +++++++++++++ .../server/initialization/server-api.test.ts | 27 +++ .../server/initialization/server-api.ts | 80 +++++++++ plugins/wazuh-core/server/plugin.ts | 16 +- plugins/wazuh-core/server/services/index.ts | 1 + .../server/services/initialization/README.md | 66 +++++++ .../server/services/initialization/index.ts | 2 + .../services/initialization/initialization.ts | 135 +++++++++++++++ .../server/services/initialization/types.ts | 19 +++ plugins/wazuh-core/server/services/types.ts | 12 ++ plugins/wazuh-core/server/types.ts | 3 + 16 files changed, 924 insertions(+), 1 deletion(-) create mode 100644 plugins/main/server/lib/initialization/index-patterns.ts create mode 100644 plugins/main/server/lib/initialization/index.ts create mode 100644 plugins/main/server/lib/initialization/settings.ts create mode 100644 plugins/main/server/lib/initialization/templates.test.ts create mode 100644 plugins/main/server/lib/initialization/templates.ts create mode 100644 plugins/wazuh-core/server/initialization/server-api.test.ts create mode 100644 plugins/wazuh-core/server/initialization/server-api.ts create mode 100644 plugins/wazuh-core/server/services/initialization/README.md create mode 100644 plugins/wazuh-core/server/services/initialization/index.ts create mode 100644 plugins/wazuh-core/server/services/initialization/initialization.ts create mode 100644 plugins/wazuh-core/server/services/initialization/types.ts create mode 100644 plugins/wazuh-core/server/services/types.ts diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/main/server/lib/initialization/index-patterns.ts new file mode 100644 index 0000000000..734e818c23 --- /dev/null +++ b/plugins/main/server/lib/initialization/index-patterns.ts @@ -0,0 +1,161 @@ +interface ensureIndexPatternExistenceContextTask { + indexPatternID: string; + options: any; +} + +interface ensureIndexPatternExistenceContextTaskWithCondifurationSetting + extends ensureIndexPatternExistenceContextTask { + configurationSettingKey: string; +} + +const decoratorCheckIsEnabled = fn => { + return async ( + ctx, + { + configurationSettingKey, + ...ctxTask + }: ensureIndexPatternExistenceContextTaskWithCondifurationSetting, + ) => { + if (await ctx.configuration.get(configurationSettingKey)) { + await fn(ctx, ctxTask); + } else { + ctx.logger.info(`Check [${configurationSettingKey}]: disabled. Skipped.`); + } + }; +}; + +export const ensureIndexPatternExistence = async ( + { logger, savedObjectsClient, indexPatternsClient }, + { indexPatternID, options = {} }: ensureIndexPatternExistenceContextTask, +) => { + try { + logger.debug( + `Checking existence of index pattern with ID [${indexPatternID}]`, + ); + const response = await savedObjectsClient.get( + 'index-pattern', + indexPatternID, + ); + logger.debug(`Index pattern with ID [${indexPatternID}] exists`); + return response; + } catch (e) { + // Get not found saved object + if (e?.output?.statusCode === 404) { + // Create index pattern + logger.info(`Index pattern with ID [${indexPatternID}] does not exist`); + return await createIndexPattern( + { logger, savedObjectsClient, indexPatternsClient }, + indexPatternID, + options, + ); + } else { + throw new Error( + `Error checking the existence of index pattern with ID [${indexPatternID}]: ${e.message}`, + ); + } + } +}; + +async function getFieldMappings( + { logger, indexPatternsClient }, + indexPatternTitle: string, +) { + logger.debug(`Getting index pattern fields for title [${indexPatternTitle}]`); + + // https://github.com/opensearch-project/OpenSearch-Dashboards/blob/2.16.0/src/plugins/data/server/index_patterns/routes.ts#L74 + const fields = await indexPatternsClient.getFieldsForWildcard({ + pattern: indexPatternTitle, + // meta_fields=_source&meta_fields=_id&meta_fields=_type&meta_fields=_index&meta_fields=_score + metaFields: ['_source', '_id', '_type', '_index', '_score'], + }); + logger.debug( + `Fields for index pattern with title [${indexPatternTitle}]: ${JSON.stringify( + fields, + )}`, + ); + return fields; +} + +async function createIndexPattern( + { logger, savedObjectsClient, indexPatternsClient }, + indexPatternID, + options: { + fieldsNoIndices?: any; + savedObjectOverwrite?: { [key: string]: any }; + } = {}, +) { + try { + let fields; + try { + fields = await getFieldMappings( + { logger, indexPatternsClient }, + indexPatternID, + ); + } catch (e) { + if (options.fieldsNoIndices) { + const message = `Fields for index pattern with ID [${indexPatternID}] could not be obtained. This could indicate there are not matching indices because they were not generated or there is some error in the process that generates and indexes that data. The index pattern will be created with a set of pre-defined fields.`; + logger.warn(message); + fields = options.fieldsNoIndices; + } else { + throw e; + } + } + + const savedObjectData = { + title: indexPatternID, + fields: JSON.stringify(fields), + ...(options?.savedObjectOverwrite || {}), + }; + + logger.debug( + `Creating index pattern with ID [${indexPatternID}] title [${savedObjectData.title}]`, + ); + + const response = await savedObjectsClient.create( + 'index-pattern', + savedObjectData, + { + id: indexPatternID, + overwrite: true, + refresh: true, + }, + ); + + const indexPatternCreatedMessage = `Created index pattern with ID [${response.id}] title [${response.attributes.title}]`; + logger.info(indexPatternCreatedMessage); + return response; + } catch (e) { + throw new Error( + `Error creating index pattern with ID [${indexPatternID}]: ${e.message}`, + ); + } +} + +export const initializationTaskCreatorIndexPattern = ({ + taskName, + options = {}, + configurationSettingKey, + ...rest +}: { + getIndexPatternID: (ctx: any) => Promise; + taskName: string; + options: {}; + configurationSettingKey: string; +}) => ({ + name: taskName, + async run(ctx) { + try { + ctx.logger.debug('Starting index pattern saved object'); + const getIndexPatternID = + ctx?.getIndexPatternID || rest.getIndexPatternID; + const indexPatternID = await getIndexPatternID(ctx); + return await ensureIndexPatternExistence(ctx, { + indexPatternID, + options, + configurationSettingKey, + }); + } catch (e) { + throw new Error(`Error initilizating index pattern ${e.message}`); + } + }, +}); diff --git a/plugins/main/server/lib/initialization/index.ts b/plugins/main/server/lib/initialization/index.ts new file mode 100644 index 0000000000..e7712b3abc --- /dev/null +++ b/plugins/main/server/lib/initialization/index.ts @@ -0,0 +1,3 @@ +export * from './index-patterns'; +export * from './settings'; +export * from './templates'; diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts new file mode 100644 index 0000000000..2414f61d50 --- /dev/null +++ b/plugins/main/server/lib/initialization/settings.ts @@ -0,0 +1,146 @@ +/* + * Wazuh app - Check PluginPlatform settings service + * + * Copyright (C) 2015-2024 Wazuh, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Find more information about this on the LICENSE file. + * + */ + +import _ from 'lodash'; + +const decoratorCheckIsEnabled = fn => { + return async ( + ctx, + { + configurationSetting, + ...ctxTask + }: { key: string; value: any; configurationSetting: string }, + ) => { + if (await ctx.configuration.get(configurationSetting)) { + await fn(ctx, ctxTask); + } else { + ctx.logger.info(`Check [${configurationSetting}]: disabled. Skipped.`); + } + }; +}; + +export const checkPluginPlatformSettings = decoratorCheckIsEnabled( + async ( + { logger, uiSettingsClient }, + { + key: pluginPlatformSettingName, + value: defaultAppValue, + }: { key: string; value: any }, + ) => { + logger.debug(`Getting setting [${pluginPlatformSettingName}]...`); + const valuePluginPlatformSetting = await uiSettingsClient.get( + pluginPlatformSettingName, + ); + const settingsAreDifferent = !_.isEqual( + valuePluginPlatformSetting, + defaultAppValue, + ); + logger.debug( + `Check setting [${pluginPlatformSettingName}]: ${stringifySetting( + valuePluginPlatformSetting, + )}`, + ); + logger.debug( + `App setting [${pluginPlatformSettingName}]: ${stringifySetting( + defaultAppValue, + )}`, + ); + logger.debug( + `Setting mismatch [${pluginPlatformSettingName}]: ${ + settingsAreDifferent ? 'yes' : 'no' + }`, + ); + logger.debug( + `Setting is user defined [${pluginPlatformSettingName}]: ${ + valuePluginPlatformSetting ? 'yes' : 'no' + }`, + ); + if (!valuePluginPlatformSetting || settingsAreDifferent) { + logger.debug(`Updating [${pluginPlatformSettingName}] setting...`); + await updateSetting( + uiSettingsClient, + pluginPlatformSettingName, + defaultAppValue, + ); + logger.info( + `Updated [${pluginPlatformSettingName}] setting to: ${stringifySetting( + defaultAppValue, + )}`, + ); + } + }, +); + +async function updateSetting( + uiSettingsClient, + pluginPlatformSettingName, + defaultAppValue, + retries = 3, +) { + return await uiSettingsClient + .set(pluginPlatformSettingName, defaultAppValue) + .catch(async error => { + if (retries > 0) { + return await updateSetting( + uiSettingsClient, + pluginPlatformSettingName, + defaultAppValue, + --retries, + ); + } + throw error; + }); +} + +function stringifySetting(setting: any) { + try { + return JSON.stringify(setting); + } catch (error) { + return setting; + } +} + +export const initializationTaskCreatorSetting = ( + setting: { key: string; value: any; configurationSetting: string }, + taskName: string, +) => ({ + name: taskName, + async run(ctx) { + try { + ctx.logger.debug('Starting setting'); + console.log({ ctx }); + const uiSettingsClient = + ctx.uiSettingsClient || + ctx.core.uiSettings.asScopedToClient(ctx.savedObjectsClient); + + const { key, value, configurationSetting } = setting; + + await checkPluginPlatformSettings( + { + logger: ctx.logger, + uiSettingsClient, + configuration: ctx.configuration, + }, + { + key, + value, + configurationSetting, + }, + ); + ctx.logger.info('Start setting finished'); + } catch (e) { + throw new Error(`Error initilizating setting ${e.message}`); + } + }, +}); diff --git a/plugins/main/server/lib/initialization/templates.test.ts b/plugins/main/server/lib/initialization/templates.test.ts new file mode 100644 index 0000000000..e00bba3548 --- /dev/null +++ b/plugins/main/server/lib/initialization/templates.test.ts @@ -0,0 +1,43 @@ +import { getTemplateForIndexPattern } from './templates'; + +const templates = [ + { + name: 'wazuh', + index_patterns: '[wazuh-alerts-4.x-*, wazuh-archives-4.x-*]', + order: '0', + version: '1', + composed_of: '', + }, + { + name: 'wazuh-agent', + index_patterns: '[wazuh-monitoring-*]', + order: '0', + version: null, + composed_of: '', + }, + { + name: 'wazuh-statistics', + index_patterns: '[wazuh-statistics-*]', + order: '0', + version: null, + composed_of: '', + }, +]; + +describe('getTemplateForIndexPattern', () => { + it.each` + indexPatternTitle | templateNameFound + ${'custom-alerts-*'} | ${[]} + ${'wazuh-alerts-*'} | ${['wazuh']} + ${'wazuh-alerts-'} | ${['wazuh']} + `( + `indexPatternTitle: $indexPatternTitle`, + ({ indexPatternTitle, templateNameFound }) => { + expect( + getTemplateForIndexPattern(indexPatternTitle, templates).map( + ({ name }) => name, + ), + ).toEqual(templateNameFound); + }, + ); +}); diff --git a/plugins/main/server/lib/initialization/templates.ts b/plugins/main/server/lib/initialization/templates.ts new file mode 100644 index 0000000000..8030fea615 --- /dev/null +++ b/plugins/main/server/lib/initialization/templates.ts @@ -0,0 +1,88 @@ +export const checkIndexPatternHasTemplate = async ( + { logger }, + { indexPatternTitle, opensearchClient }, +) => { + logger.debug('Getting templates'); + const data = await opensearchClient.cat.templates({ format: 'json' }); + + logger.debug( + 'Checking the index pattern with title [${indexPatternTitle}] has defined some template', + ); + const templatesFound = getTemplateForIndexPattern( + indexPatternTitle, + data.body, + ); + if (!templatesFound.length) { + throw new Error( + `No template found for index pattern with title [${indexPatternTitle}]`, + ); + } + + logger.info( + `Template [${templatesFound + .map(({ name }) => name) + .join( + ', ', + )}] found for index pattern with title [${indexPatternTitle}]: `, + ); +}; + +export function getTemplateForIndexPattern( + indexPatternTitle: string, + templates: { name: string; index_patterns: string }[], +) { + return templates.filter(({ index_patterns }: { index_patterns: string }) => { + const [, cleanIndexPatterns] = index_patterns.match(/\[(.+)\]/) || [ + null, + null, + ]; + if (!cleanIndexPatterns) { + return false; + } + const indexPatterns = cleanIndexPatterns.match(/([^\s,]+)/g); + + if (!indexPatterns) { + return false; + } + + const lastChar = indexPatternTitle[indexPatternTitle.length - 1]; + const indexPatternTitleCleaned = + lastChar === '*' ? indexPatternTitle.slice(0, -1) : indexPatternTitle; + return indexPatterns.some(indexPattern => { + const lastChar = indexPattern[indexPattern.length - 1]; + const indexPatternCleaned = + lastChar === '*' ? indexPattern.slice(0, -1) : indexPattern; + return ( + indexPatternCleaned.includes(indexPatternTitleCleaned) || + indexPatternTitleCleaned.includes(indexPatternCleaned) + ); + }); + }); +} + +export const initializationTaskCreatorExistTemplate = ({ + getOpenSearchClient, + getIndexPatternTitle, + taskName, +}: { + getOpenSearchClient: (ctx: any) => any; + getIndexPatternTitle: (ctx: any) => Promise; + taskName: string; +}) => ({ + name: taskName, + async run(ctx) { + try { + ctx.logger.debug('Starting check of existent template'); + + const opensearchClient = getOpenSearchClient(ctx); + const indexPatternTitle = await getIndexPatternTitle(ctx); + await checkIndexPatternHasTemplate(ctx, { + opensearchClient, + indexPatternTitle, + }); + ctx.logger.info('Start check of existent template finished'); + } catch (e) { + ctx.logger.error(`Error checking of existent template: ${e.message}`); + } + }, +}); diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index e37ec01792..31983be561 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -37,6 +37,22 @@ import { jobSanitizeUploadedFilesTasksRun, } from './start'; import { first } from 'rxjs/operators'; +import { + initializationTaskCreatorIndexPattern, + initializationTaskCreatorSetting, + initializationTaskCreatorExistTemplate, +} from './lib/initialization'; +import { + PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, + PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, + PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, + WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, + WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, + WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER, +} from '../common/constants'; +import { KnownFields } from '../public/utils/known-fields'; +import { FieldsStatistics } from '../public/utils/statistics-fields'; +import { FieldsMonitoring } from '../public/utils/monitoring-fields'; declare module 'opensearch_dashboards/server' { interface RequestHandlerContext { @@ -109,6 +125,113 @@ export class WazuhPlugin implements Plugin { const router = core.http.createRouter(); setupRoutes(router, plugins.wazuhCore); + // Register initialization + // Index pattern: alerts + // TODO: this task should be registered by the related plugin + plugins.wazuhCore.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => ctx.configuration.get('pattern'), + taskName: 'index-pattern:alerts', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: KnownFields, + }, + configurationSettingKey: 'checks.pattern', + }), + ); + // Index pattern: monitoring + // TODO: this task should be registered by the related plugin + plugins.wazuhCore.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => + ctx.configuration.get('wazuh.monitoring.pattern'), + taskName: 'index-pattern:monitoring', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: FieldsMonitoring, + }, + configurationSettingKey: 'checks.monitoring', + }), + ); + // Index pattern: vulnerabilities + // TODO: this task should be registered by the related plugin + plugins.wazuhCore.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => + ctx.configuration.get('vulnerabilities.pattern'), + taskName: 'index-pattern:vulnerabilities-states', + options: { + // fieldsNoIndices: JSON.stringify(FieldsStatistics), // TODO: add fallback fields + }, + configurationSettingKey: 'checks.monitoring', + }), + ); + + // Index pattern: statistics + // TODO: this task should be registered by the related plugin + plugins.wazuhCore.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: async ctx => { + const appConfig = await ctx.configuration.get( + 'cron.prefix', + 'cron.statistics.index.name', + ); + + const prefixTemplateName = appConfig['cron.prefix']; + const statisticsIndicesTemplateName = + appConfig['cron.statistics.index.name']; + return `${prefixTemplateName}-${statisticsIndicesTemplateName}-*`; + }, + taskName: 'index-pattern:statistics', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: FieldsStatistics, + }, + configurationSettingKey: 'checks.statistics', + }), + ); + + // Settings + // TODO: this task should be registered by the related plugin + [ + { + key: PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, + value: WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, + configurationSetting: 'checks.maxBuckets', + }, + { + key: PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, + value: WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, + configurationSetting: 'checks.metaFields', + }, + { + key: PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, + value: JSON.stringify(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER), + configurationSetting: 'checks.timeFilter', + }, + ].forEach(setting => { + plugins.wazuhCore.initialization.register( + initializationTaskCreatorSetting(setting, `setting:${setting.key}`), + ); + }); + + // Index pattern templates + // Index pattern template: alerts + // TODO: this task should be registered by the related plugin + plugins.wazuhCore.initialization.register( + initializationTaskCreatorExistTemplate({ + getOpenSearchClient: ctx => ctx.core.opensearch.client.asInternalUser, + getIndexPatternTitle: ctx => ctx.configuration.get('pattern'), + taskName: 'index-pattern-template:alerts', + }), + ); + return {}; } diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts new file mode 100644 index 0000000000..d8b4b93b34 --- /dev/null +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -0,0 +1,27 @@ +import { checkAppServerCompatibility } from './server-api'; + +describe('checkAppServerCompatibility', () => { + it.each` + appVersion | serverAPIVersion | result + ${'5.0.0'} | ${'5.0.0'} | ${true} + ${'5.0.0'} | ${'5.0.1'} | ${true} + ${'5.0.0'} | ${'5.0.10'} | ${true} + ${'5.0.0'} | ${'5.0.100'} | ${true} + ${'5.0.0'} | ${'4.9.1'} | ${false} + ${'5.0.0'} | ${'4.9.10'} | ${false} + ${'5.0.0'} | ${'4.9.100'} | ${false} + ${'5.0.0'} | ${'4.0.1'} | ${false} + ${'5.0.0'} | ${'4.0.10'} | ${false} + ${'5.0.0'} | ${'4.0.100'} | ${false} + ${'5.0.0'} | ${'4.10.1'} | ${false} + ${'5.0.0'} | ${'4.10.10'} | ${false} + ${'5.0.0'} | ${'4.10.100'} | ${false} + `( + `appVersion: $appVersion, serverAPIVersion: $serverAPIVersion, result: $result`, + ({ appVersion, serverAPIVersion, result }) => { + expect(checkAppServerCompatibility(appVersion, serverAPIVersion)).toBe( + result, + ); + }, + ); +}); diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts new file mode 100644 index 0000000000..da1a5a38a0 --- /dev/null +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -0,0 +1,80 @@ +import { + PLUGIN_APP_NAME, + PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, +} from '../../common/constants'; +import { webDocumentationLink } from '../../common/services/web_documentation'; +import { version as appVersion } from '../../package.json'; + +export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ + taskName, +}: { + taskName: string; +}) => ({ + name: taskName, + async run(ctx) { + try { + ctx.logger.debug( + 'Starting check server API connection and compatibility', + ); + await ServerAPIConnectionCompatibility(ctx); + ctx.logger.info( + 'Start check server API connection and compatibility finished', + ); + } catch (e) { + ctx.logger.error( + `Error checking server API connection and compatibility: ${e.message}`, + ); + } + }, +}); + +export async function ServerAPIConnectionCompatibility(ctx) { + const hosts = await ctx.manageHosts.get(undefined, { + excludePassword: true, + }); + + ctx.logger.debug(`APP version [${appVersion}]`); + + await Promise.all( + hosts.map(async ({ id: apiHostID }) => { + try { + ctx.logger.debug( + `Checking the connection and compatibility with server API [${apiHostID}]`, + ); + const response = await ctx.serverAPIClient.asInternalUser.request( + 'GET', + '/', + {}, + { apiHostID }, + ); + const { api_version: serverAPIVersion } = response?.data?.data; + if (!serverAPIVersion) { + throw new Error('version is not found in the response of server API'); + } + ctx.logger.debug(`Server API version [${serverAPIVersion}]`); + if (!checkAppServerCompatibility(appVersion, serverAPIVersion)) { + ctx.logger.warn( + `Server API version [${serverAPIVersion}] is not compatible with the ${PLUGIN_APP_NAME} version [${apiVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( + PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, + )}.`, + ); + } + } catch (e) { + ctx.logger.error( + `Error checking the connection and compatibility with server API [${apiHostID}]: ${e.message}`, + ); + } + }), + ); +} + +export function checkAppServerCompatibility(appVersion, serverAPIVersion) { + const api = /v?(?\d+)\.(?\d+)\.(?\d+)/.exec( + serverAPIVersion, + ); + const [appVersionMajor, appVersionMinor] = appVersion.split('.'); + return ( + api?.groups?.major === appVersionMajor && + api?.groups?.minor === appVersionMinor + ); +} diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index 4c1587ce50..5eeaa98a13 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -16,8 +16,8 @@ import { ManageHosts, createDashboardSecurity, ServerAPIClient, - UpdateRegistry, ConfigurationStore, + InitializationService, } from './services'; import { Configuration } from '../common/services/configuration'; import { @@ -27,6 +27,7 @@ import { WAZUH_DATA_CONFIG_APP_PATH, } from '../common/constants'; import { enhanceConfiguration } from './services/enhance-configuration'; +import { initializationTaskCreatorServerAPIConnectionCompatibility } from './initialization/server-api'; export class WazuhCorePlugin implements Plugin @@ -107,6 +108,18 @@ export class WazuhCorePlugin this.services.manageHosts.setServerAPIClient(this.services.serverAPIClient); + this.services.initialization = new InitializationService( + this.logger.get('initialization'), + this.services, + ); + + // Register initialization tasks + this.services.initialization.register( + initializationTaskCreatorServerAPIConnectionCompatibility({ + taskName: 'check-server-api-connection-compatibility', + }), + ); + // Register a property to the context parameter of the endpoint handlers core.http.registerRouteHandlerContext('wazuh_core', (context, request) => { return { @@ -141,6 +154,7 @@ export class WazuhCorePlugin await this.services.configuration.start(); await this.services.manageHosts.start(); + await this.services.initialization.start({ core }); return { ...this.services, diff --git a/plugins/wazuh-core/server/services/index.ts b/plugins/wazuh-core/server/services/index.ts index 8a794e559f..9b064c7e99 100644 --- a/plugins/wazuh-core/server/services/index.ts +++ b/plugins/wazuh-core/server/services/index.ts @@ -16,3 +16,4 @@ export * from './filesystem'; export * from './manage-hosts'; export * from './security-factory'; export * from './server-api-client'; +export * from './initialization'; diff --git a/plugins/wazuh-core/server/services/initialization/README.md b/plugins/wazuh-core/server/services/initialization/README.md new file mode 100644 index 0000000000..ae894e95f3 --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/README.md @@ -0,0 +1,66 @@ +# InitializationService + +The `InitializationService` provides a mechanism to register and run tasks when the `wazuhCore` plugin starts (plugin lifecycle). + +Other plugins can register tasks in the plugin `setup` lifecycle that will be run on the `wazuhCore` plugin starts. + +The tasks run on parallel. + +Optionally the registered tasks could be retrieved to run in API endpoints or getting information about its status. + +# InitializationService tasks + +A task can be defined with: + +```ts +interface InitializationTaskDefinition { + name: string; + run: (ctx: any) => any; +} +``` + +The `ctx` is the context of the task execution and includes core services and task context services or dependencies. + +The `name` is used to identify the task and this is rendered in the context logger. + +For example, in the server log: + +``` +server log [11:57:39.648] [info][index-pattern-vulnerabilities-states][initialization][plugins][wazuhCore] Index pattern with ID [wazuh-states-vulnerabilities-*] does not exist + +``` + +the task name is `index-pattern-vulnerabilities-states`. + +## Register a task + +```ts +// plugin setup +setup(){ + + // Register a task + plugins.wazuhCore.register({ + name: 'custom-task', + run: (ctx) => { + console.log('Run from wazuhCore starts' ) + } + }); + +} +``` + +## Task data + +The task has the following data related to the execution: + +```ts +interface InitializationTaskRunData { + status: 'not_started' | 'running' | 'finished'; + result: 'success' | 'fail'; + startAt: number | null; + endAt: number | null; + duration: number | null; + data: any; + error: string | null; +} +``` diff --git a/plugins/wazuh-core/server/services/initialization/index.ts b/plugins/wazuh-core/server/services/initialization/index.ts new file mode 100644 index 0000000000..c7f504bd7b --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/index.ts @@ -0,0 +1,2 @@ +export * from './initialization'; +export * from './types'; diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts new file mode 100644 index 0000000000..d058727e5b --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -0,0 +1,135 @@ +import { Logger } from 'opensearch-dashboards/server'; +import { IndexPatternsFetcher } from '../../../../../src/plugins/data/server'; +import { + InitializationTaskDefinition, + IInitializationService, + InitializationTaskRunData, +} from './types'; + +export class InitializationService implements IInitializationService { + private items: Map; + constructor(private logger: Logger, private services: any) { + this.items = new Map(); + } + async setup() { + this.logger.debug('Setup'); + } + async start({ core }) { + try { + this.logger.debug('Starting'); + const savedObjectsClient = core.savedObjects.createInternalRepository(); + const indexPatternsClient = new IndexPatternsFetcher( + core.opensearch.legacy.client.callAsInternalUser, + ); + if (this.items.size) { + await Promise.all( + Array.from(this.items.entries()).map(async ([name, item]) => { + const logger = this.logger.get(name); + try { + await item.run({ + ...this.services, + core, + savedObjectsClient, + indexPatternsClient, + logger, + }); + } catch (e) { + logger.error(`Error running task [${name}]: ${e.message}`); + } + }), + ); + + this.logger.info('Start finished'); + } else { + this.logger.info('No tasks'); + } + } catch (error) { + this.logger.error(`Error starting: ${error.message}`); + } + } + async stop() { + this.logger.debug('Stop'); + } + register(task: InitializationTaskDefinition) { + this.logger.debug(`Registering ${task.name}`); + if (this.items.has(task.name)) { + throw new Error( + `[${task.name}] was already registered. Ensure the name is unique or remove the duplicated registration of same task.`, + ); + } + this.items.set(task.name, new InitializationTask(task)); + this.logger.debug(`Registered ${task.name}`); + } + get(taskName?: string) { + this.logger.debug(`Getting tasks: ${taskName ? `[${taskName}]` : ''}`); + if (taskName) { + return this.items.get(taskName); + } + return Array.from(this.items.values()); + } +} + +class InitializationTask implements InitializationTaskRunData { + public name: string; + private _run: any; + public status: InitializationTaskRunData['status'] = 'not_started'; + public result: InitializationTaskRunData['result'] = null; + public data: any = null; + public startAt: number | null = null; + public endAt: number | null = null; + public duration: number | null = null; + public error: string | null = null; + constructor(task: InitializationTaskDefinition) { + this.name = task.name; + this._run = task.run; + } + private init() { + this.status = 'running'; + this.result = null; + this.data = null; + this.startAt = Date.now(); + this.endAt = null; + this.duration = null; + this.error = null; + } + private setResult(result) { + this.result = result; + } + async run(...params) { + let error; + try { + this.init(); + this.data = await this._run(...params); + this.setResult('success'); + } catch (e) { + error = e; + this.setResult('fail'); + this.error = e.message; + } finally { + this.status = 'finished'; + this.endAt = Date.now(); + this.duration = this.endAt - (this.startAt as number); + } + if (error) { + throw error; + } + return this.data; + } + getStatus() { + return [ + 'status', + 'result', + 'data', + 'startAt', + 'endAt', + 'duration', + 'error', + ].reduce( + (accum, item) => ({ + ...accum, + [item]: this[item], + }), + {}, + ); + } +} diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts new file mode 100644 index 0000000000..0ec0a74842 --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -0,0 +1,19 @@ +import { LifecycleService } from '../types'; + +export interface InitializationTaskRunData { + status: 'not_started' | 'running' | 'finished'; + result: 'success' | 'fail' | null; + startAt: number | null; + endAt: number | null; + duration: number | null; + data: any; + error: string | null; +} + +export interface InitializationTaskDefinition { + name: string; + run: (ctx: any) => any; +} + +export interface IInitializationService + extends LifecycleService {} diff --git a/plugins/wazuh-core/server/services/types.ts b/plugins/wazuh-core/server/services/types.ts new file mode 100644 index 0000000000..bb6c43c39f --- /dev/null +++ b/plugins/wazuh-core/server/services/types.ts @@ -0,0 +1,12 @@ +export interface LifecycleService< + SetupDeps, + SetupReturn, + StartDeps, + StartReturn, + StopDeps, + StopReturn, +> { + setup: (deps: SetupDeps) => SetupReturn; + start: (deps: StartDeps) => StartReturn; + stop: (deps: StopDeps) => StopReturn; +} diff --git a/plugins/wazuh-core/server/types.ts b/plugins/wazuh-core/server/types.ts index 509a74600f..f706b3ef28 100644 --- a/plugins/wazuh-core/server/types.ts +++ b/plugins/wazuh-core/server/types.ts @@ -1,4 +1,5 @@ import { + IInitializationService, ISecurityFactory, ManageHosts, ServerAPIClient, @@ -13,6 +14,7 @@ export interface WazuhCorePluginSetup { configuration: IConfigurationEnhanced; manageHosts: ManageHosts; serverAPIClient: ServerAPIClient; + initialization: IInitializationService; api: { client: { asInternalUser: ServerAPIInternalUserClient; @@ -26,6 +28,7 @@ export interface WazuhCorePluginStart { configuration: IConfigurationEnhanced; manageHosts: ManageHosts; serverAPIClient: ServerAPIClient; + initialization: IInitializationService; api: { client: { asInternalUser: ServerAPIInternalUserClient; From 710774b00d44f7c484b282ab0dc08ebc5b4f7334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 8 Nov 2024 09:40:32 +0100 Subject: [PATCH 02/30] fix: call method of saved object service --- .../hocs/validate-vulnerabilities-states-index-pattern.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx b/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx index 5e47789b24..c5c819eab2 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx @@ -28,7 +28,7 @@ async function checkExistenceIndices(indexPatternId: string) { async function createIndexPattern(indexPattern, fields: any) { try { - await SavedObject.createSavedObjectIndexPattern( + await SavedObject.createSavedObject( 'index-pattern', indexPattern, { From 5f94e00628bcf989e4e673f6c265d0db9c6d42e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 8 Nov 2024 10:30:28 +0100 Subject: [PATCH 03/30] chore: remove console.log --- plugins/main/server/lib/initialization/settings.ts | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts index 2414f61d50..a571db9c6b 100644 --- a/plugins/main/server/lib/initialization/settings.ts +++ b/plugins/main/server/lib/initialization/settings.ts @@ -119,7 +119,6 @@ export const initializationTaskCreatorSetting = ( async run(ctx) { try { ctx.logger.debug('Starting setting'); - console.log({ ctx }); const uiSettingsClient = ctx.uiSettingsClient || ctx.core.uiSettings.asScopedToClient(ctx.savedObjectsClient); From f76784a1472eebab7134a5aae410b8dd08f75f77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 11 Nov 2024 14:12:54 +0100 Subject: [PATCH 04/30] feat(initialization): add API endpoints to manage the initialization tasks - Add API endpoints to manage the initialization tasks - Move injectected depencencies to get in each task - Add scopes to differenciate where the task is called --- .../lib/initialization/index-patterns.ts | 69 ++++- .../server/lib/initialization/settings.ts | 41 ++- plugins/wazuh-core/server/plugin.ts | 5 + .../services/initialization/initialization.ts | 150 ++++++----- .../server/services/initialization/routes.ts | 242 ++++++++++++++++++ .../server/services/initialization/types.ts | 34 ++- 6 files changed, 466 insertions(+), 75 deletions(-) create mode 100644 plugins/wazuh-core/server/services/initialization/routes.ts diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/main/server/lib/initialization/index-patterns.ts index 734e818c23..083cd8e018 100644 --- a/plugins/main/server/lib/initialization/index-patterns.ts +++ b/plugins/main/server/lib/initialization/index-patterns.ts @@ -1,3 +1,5 @@ +import { IndexPatternsFetcher } from '../../../../../src/plugins/data/server'; + interface ensureIndexPatternExistenceContextTask { indexPatternID: string; options: any; @@ -131,6 +133,51 @@ async function createIndexPattern( } } +function getSavedObjectsClient(ctx: any, scope) { + switch (scope) { + case 'internal': + return ctx.core.savedObjects.createInternalRepository(); + break; + case 'user': + return ctx.core.savedObjects.savedObjectsStart.getScopedClient( + ctx.request, + ); + break; + default: + break; + } +} + +function getIndexPatternsClient(ctx: any, scope) { + switch (scope) { + case 'internal': + return new IndexPatternsFetcher( + ctx.core.opensearch.legacy.client.callAsCurrentUser, + ); + break; + case 'user': + return new IndexPatternsFetcher( + ctx.core.opensearch.legacy.client.callAsCurrentUser, + ); + break; + default: + break; + } +} + +function getIndexPatternID(ctx: any, scope: string, rest: any) { + switch (scope) { + case 'internal': + return rest.getIndexPatternID(ctx); + break; + case 'user': + return ctx.getIndexPatternID(ctx); + break; + default: + break; + } +} + export const initializationTaskCreatorIndexPattern = ({ taskName, options = {}, @@ -146,14 +193,20 @@ export const initializationTaskCreatorIndexPattern = ({ async run(ctx) { try { ctx.logger.debug('Starting index pattern saved object'); - const getIndexPatternID = - ctx?.getIndexPatternID || rest.getIndexPatternID; - const indexPatternID = await getIndexPatternID(ctx); - return await ensureIndexPatternExistence(ctx, { - indexPatternID, - options, - configurationSettingKey, - }); + const indexPatternID = await getIndexPatternID(ctx, ctx.scope, rest); + + // Get clients depending on the scope + const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); + const indexPatternsClient = getIndexPatternsClient(ctx, ctx.scope); + + return await ensureIndexPatternExistence( + { ...ctx, indexPatternsClient, savedObjectsClient }, + { + indexPatternID, + options, + configurationSettingKey, + }, + ); } catch (e) { throw new Error(`Error initilizating index pattern ${e.message}`); } diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts index a571db9c6b..58f41d374b 100644 --- a/plugins/main/server/lib/initialization/settings.ts +++ b/plugins/main/server/lib/initialization/settings.ts @@ -111,6 +111,36 @@ function stringifySetting(setting: any) { } } +function getSavedObjectsClient(ctx: any, scope) { + switch (scope) { + case 'internal': + return ctx.core.savedObjects.createInternalRepository(); + break; + case 'user': + return ctx.core.savedObjects.savedObjectsStart.getScopedClient( + ctx.request, + ); + break; + default: + break; + } +} + +function getUiSettingsClient(ctx, scope, client) { + switch (scope) { + case 'internal': + return ctx.core.uiSettings.asScopedToClient(client); + break; + + case 'user': + return ctx.core.uiSettings.uiSettingsStart.asScopedToClient(client); + break; + + default: + break; + } +} + export const initializationTaskCreatorSetting = ( setting: { key: string; value: any; configurationSetting: string }, taskName: string, @@ -119,9 +149,14 @@ export const initializationTaskCreatorSetting = ( async run(ctx) { try { ctx.logger.debug('Starting setting'); - const uiSettingsClient = - ctx.uiSettingsClient || - ctx.core.uiSettings.asScopedToClient(ctx.savedObjectsClient); + + // Get clients depending on the scope + const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); + const uiSettingsClient = getUiSettingsClient( + ctx, + ctx.scope, + savedObjectsClient, + ); const { key, value, configurationSetting } = setting; diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index 5eeaa98a13..3cad414216 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -113,6 +113,8 @@ export class WazuhCorePlugin this.services, ); + this.services.initialization.setup({ core }); + // Register initialization tasks this.services.initialization.register( initializationTaskCreatorServerAPIConnectionCompatibility({ @@ -124,6 +126,9 @@ export class WazuhCorePlugin core.http.registerRouteHandlerContext('wazuh_core', (context, request) => { return { ...this.services, + logger: this.logger.get( + `${request.route.method.toUpperCase()} ${request.route.path}`, + ), api: { client: { asInternalUser: this.services.serverAPIClient.asInternalUser, diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index d058727e5b..d79531b9e3 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -1,45 +1,94 @@ import { Logger } from 'opensearch-dashboards/server'; -import { IndexPatternsFetcher } from '../../../../../src/plugins/data/server'; import { InitializationTaskDefinition, IInitializationService, InitializationTaskRunData, + IInitializationTask, + InitializationTaskContext, } from './types'; +import { addRoutes } from './routes'; export class InitializationService implements IInitializationService { private items: Map; + private _coreStart: any; constructor(private logger: Logger, private services: any) { this.items = new Map(); } - async setup() { - this.logger.debug('Setup'); + async setup({ core }) { + this.logger.debug('Setup starts'); + this.logger.debug('Adding routes'); + const router = core.http.createRouter(); + addRoutes(router, { initialization: this }); + this.logger.debug('Added routes'); + this.logger.debug('Setup finished'); } async start({ core }) { - try { - this.logger.debug('Starting'); - const savedObjectsClient = core.savedObjects.createInternalRepository(); - const indexPatternsClient = new IndexPatternsFetcher( - core.opensearch.legacy.client.callAsInternalUser, + this.logger.debug('Start starts'); + this._coreStart = core; + await this.runAsInternal(); + this.logger.debug('Start finished'); + } + async stop() { + this.logger.debug('Stop starts'); + this.logger.debug('Stop finished'); + } + register(task: InitializationTaskDefinition) { + this.logger.debug(`Registering ${task.name}`); + if (this.items.has(task.name)) { + throw new Error( + `[${task.name}] was already registered. Ensure the name is unique or remove the duplicated registration of same task.`, ); + } + this.items.set(task.name, new InitializationTask(task)); + this.logger.debug(`Registered ${task.name}`); + } + get(name?: string) { + this.logger.debug(`Getting tasks: ${name ? `[${name}]` : ''}`); + if (name) { + return this.items.get(name); + } + return Array.from(this.items.values()); + } + createRunContext(scope: InitializationTaskContext, context: any = {}) { + return { ...this.services, ...context, scope }; + } + async runAsInternal(taskNames?: string[]) { + const ctx = this.createRunContext('internal', { core: this._coreStart }); + return await this.run(ctx, taskNames); + } + createNewTaskFromRegisteredTask(name: string) { + const task = this.get(name) as InitializationTask; + if (!task) { + throw new Error(`Task [${name}] is not registered`); + } + return new InitializationTask({ name, run: task._run }); + } + private async run(ctx, taskNames?: string[]) { + try { if (this.items.size) { - await Promise.all( - Array.from(this.items.entries()).map(async ([name, item]) => { - const logger = this.logger.get(name); + const allTasks = Array.from(this.items.values()); + const tasks = taskNames + ? allTasks.filter(({ name }) => + taskNames.some(taskName => taskName === name), + ) + : allTasks; + const results = await Promise.all( + tasks.map(async item => { + const logger = this.logger.get(item.name); + try { - await item.run({ + return await item.run({ ...this.services, - core, - savedObjectsClient, - indexPatternsClient, + ...ctx, logger, }); } catch (e) { - logger.error(`Error running task [${name}]: ${e.message}`); + logger.error(`Error running task [${item.name}]: ${e.message}`); + return item.getInfo(); } }), ); - - this.logger.info('Start finished'); + return results; } else { this.logger.info('No tasks'); } @@ -47,38 +96,20 @@ export class InitializationService implements IInitializationService { this.logger.error(`Error starting: ${error.message}`); } } - async stop() { - this.logger.debug('Stop'); - } - register(task: InitializationTaskDefinition) { - this.logger.debug(`Registering ${task.name}`); - if (this.items.has(task.name)) { - throw new Error( - `[${task.name}] was already registered. Ensure the name is unique or remove the duplicated registration of same task.`, - ); - } - this.items.set(task.name, new InitializationTask(task)); - this.logger.debug(`Registered ${task.name}`); - } - get(taskName?: string) { - this.logger.debug(`Getting tasks: ${taskName ? `[${taskName}]` : ''}`); - if (taskName) { - return this.items.get(taskName); - } - return Array.from(this.items.values()); - } } -class InitializationTask implements InitializationTaskRunData { +class InitializationTask implements IInitializationTask { public name: string; private _run: any; public status: InitializationTaskRunData['status'] = 'not_started'; public result: InitializationTaskRunData['result'] = null; public data: any = null; - public startAt: number | null = null; - public endAt: number | null = null; - public duration: number | null = null; - public error: string | null = null; + public createdAt: InitializationTaskRunData['createdAt'] = + new Date().toISOString(); + public startedAt: InitializationTaskRunData['startedAt'] = null; + public finishedAt: InitializationTaskRunData['finishedAt'] = null; + public duration: InitializationTaskRunData['duration'] = null; + public error = null; constructor(task: InitializationTaskDefinition) { this.name = task.name; this._run = task.run; @@ -87,41 +118,46 @@ class InitializationTask implements InitializationTaskRunData { this.status = 'running'; this.result = null; this.data = null; - this.startAt = Date.now(); - this.endAt = null; + this.startedAt = new Date().toISOString(); + this.finishedAt = null; this.duration = null; this.error = null; } - private setResult(result) { - this.result = result; - } async run(...params) { + if (this.status === 'running') { + throw new Error(`Another instance of task ${this.name} is running`); + } let error; try { this.init(); this.data = await this._run(...params); - this.setResult('success'); + this.result = 'success'; } catch (e) { error = e; - this.setResult('fail'); + this.result = 'fail'; this.error = e.message; } finally { this.status = 'finished'; - this.endAt = Date.now(); - this.duration = this.endAt - (this.startAt as number); + this.finishedAt = new Date().toISOString(); + const dateStartedAt = new Date(this.startedAt!); + const dateFinishedAt = new Date(this.finishedAt); + this.duration = ((dateFinishedAt - dateStartedAt) as number) / 1000; } if (error) { throw error; } - return this.data; + return this.getInfo(); } - getStatus() { + + getInfo() { return [ + 'name', 'status', 'result', 'data', - 'startAt', - 'endAt', + 'createdAt', + 'startedAt', + 'finishedAt', 'duration', 'error', ].reduce( @@ -130,6 +166,6 @@ class InitializationTask implements InitializationTaskRunData { [item]: this[item], }), {}, - ); + ) as IInitializationTask; } } diff --git a/plugins/wazuh-core/server/services/initialization/routes.ts b/plugins/wazuh-core/server/services/initialization/routes.ts new file mode 100644 index 0000000000..cf7e523827 --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/routes.ts @@ -0,0 +1,242 @@ +import { schema } from '@osd/config-schema'; + +export function addRoutes(router, { initialization }) { + const getTaskList = (tasksAsString: string) => tasksAsString.split(','); + + const validateTaskList = schema.maybe( + schema.string({ + validate(value: string) { + const tasks = initialization.get(); + const requestTasks = getTaskList(value); + const invalidTasks = requestTasks.filter(requestTask => + tasks.every(({ name }) => requestTask !== name), + ); + if (invalidTasks.length) { + return `Invalid tasks: ${invalidTasks.join(', ')}`; + } + return undefined; + }, + }), + ); + + const apiEndpointBase = '/api/initialization'; + + // Get the status of internal initialization tasks + router.get( + { + path: `${apiEndpointBase}/internal`, + validate: { + tasks: schema.object({ + tasks: validateTaskList, + }), + }, + }, + async (context, request, response) => { + try { + const tasksNames = request.query.tasks + ? getTaskList(request.query.tasks) + : undefined; + const logger = context.wazuh_core.logger; + logger.debug(`Getting initialization tasks related to internal scope`); + const tasks = tasksNames + ? tasksNames.map(taskName => + context.wazuh_core.initialization.get(taskName), + ) + : context.wazuh_core.initialization.get(); + + const tasksData = tasks.map(task => task.getInfo()); + + logger.debug( + `Initialzation tasks related to internal scope: [${[...tasksData] + .map(({ name }) => name) + .join(', ')}]`, + ); + + return response.ok({ + body: { + message: `All initialization tasks are returned: ${tasks + .map(({ name }) => name) + .join(', ')}`, + tasks: tasksData, + }, + }); + } catch (e) { + return response.internalError({ + body: { + message: `Error getting the internal initialization tasks: ${e.message}`, + }, + }); + } + }, + ); + + // Run the internal initialization tasks + // TODO: protect with administrator privilegies + router.post( + { + path: `${apiEndpointBase}/internal`, + validate: { + query: schema.object({ + tasks: validateTaskList, + }), + }, + }, + async (context, request, response) => { + try { + const tasksNames = request.query.tasks + ? getTaskList(request.query.tasks) + : undefined; + const logger = context.wazuh_core.logger; + + logger.debug(`Running initialization tasks related to internal scope`); + const results = await context.wazuh_core.initialization.runAsInternal( + tasksNames, + ); + logger.info( + `Initialization tasks related to internal scope were executed`, + ); + + return response.ok({ + body: { + message: `All initialization tasks are returned: ${results + .map(({ name }) => name) + .join(', ')}`, + tasks: results, + }, + }); + } catch (e) { + return response.internalError({ + body: { + message: `Error running the internal initialization tasks: ${e.message}`, + }, + }); + } + }, + ); + + router.post( + { + path: `${apiEndpointBase}/user`, + validate: { + // TODO: restrict to user tasks + query: schema.object({ + tasks: validateTaskList, + }), + }, + }, + async (context, request, response) => { + try { + const tasksNames = request.query.tasks + ? getTaskList(request.query.tasks) + : undefined; + const logger = context.wazuh_core.logger; + const username = ''; // TODO: get value + const scope = 'user'; + logger.debug( + `Getting initialization tasks related to user [${username}] scope [${scope}]`, + ); + const initializationTasks = context.wazuh_core.initialization.get(); + + const indexPatternTasks = initializationTasks + .filter(({ name }) => name.startsWith('index-pattern:')) + .map(({ name }) => + context.wazuh_core.initialization.createNewTaskFromRegisteredTask( + name, + ), + ); + const settingsTasks = initializationTasks + .filter(({ name }) => name.startsWith('setting:')) + .map(({ name }) => + context.wazuh_core.initialization.createNewTaskFromRegisteredTask( + name, + ), + ); + + const allUserTasks = [...indexPatternTasks, ...settingsTasks]; + const tasks = tasksNames + ? allUserTasks.filter(({ name }) => + tasksNames.some(taskName => taskName === name), + ) + : allUserTasks; + + logger.debug( + `Initialzation tasks related to user [${username}] scope [${scope}]: [${tasks + .map(({ name }) => name) + .join(', ')}]`, + ); + + const taskContext = context.wazuh_core.initialization.createRunContext( + 'user', + { core: context.core, request }, + ); + + logger.debug(`Running tasks for user [${username}] scope [${scope}]`); + const results = await Promise.all( + tasks.map(async task => { + const taskLogger = enhanceTaskLogger(logger); + let data; + try { + data = await task.run({ + ...taskContext, + // TODO: use user selection index patterns + logger: taskLogger, + ...(task.name.includes('index-pattern:') + ? { + getIndexPatternID: () => + task.name /* TODO: use request parameters/body/cookies */, + } + : {}), + }); + } catch (e) { + } finally { + return { + logs: taskLogger.getLogs(), + ...task.getInfo(), + }; + } + }), + ); + + logger.debug(`All tasks for user [${username}] scope [${scope}] run`); + + const initialMessage = + 'All the initialization tasks related to user scope were executed.'; + + const message = [ + initialMessage, + results.some(({ error }) => error) && 'There was some errors.', + ] + .filter(v => v) + .join(' '); + + return response.ok({ + body: { + message, + tasks: results, + }, + }); + } catch (e) { + return response.internalError({ + body: { + message: `Error initializating the tasks: ${e.message}`, + }, + }); + } + }, + ); +} + +function enhanceTaskLogger(logger) { + const logs = []; + + return ['debug', 'info', 'warn', 'error'].reduce( + (accum, level) => ({ + ...accum, + [level]: message => { + logs.push({ timestamp: new Date().toISOString(), level, message }); + logger[level].message; + }, + }), + { getLogs: () => logs }, + ); +} diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index 0ec0a74842..e08faee1f4 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -1,19 +1,39 @@ import { LifecycleService } from '../types'; +export interface InitializationTaskDefinition { + name: string; + run: (ctx: any) => any; +} + export interface InitializationTaskRunData { + name: InitializationTaskDefinition['name']; status: 'not_started' | 'running' | 'finished'; result: 'success' | 'fail' | null; - startAt: number | null; - endAt: number | null; - duration: number | null; + createdAt: string | null; + startedAt: string | null; + finishedAt: string | null; + duration: number | null; // seconds data: any; error: string | null; } -export interface InitializationTaskDefinition { - name: string; - run: (ctx: any) => any; +export interface IInitializationTask extends InitializationTaskRunData { + run(ctx: any): Promise; + getInfo(): InitializationTaskRunData; } +export type InitializationTaskContext = 'internal' | 'user'; export interface IInitializationService - extends LifecycleService {} + extends LifecycleService { + register(task: InitializationTaskDefinition): void; + get( + taskName?: string, + ): InitializationTaskRunData | InitializationTaskRunData[]; + createRunContext( + scope: InitializationTaskContext, + context: any, + ): { + scope: InitializationTaskContext; + }; + runAsInternal(tasks?: string[]): Promise; +} From 11e40e9699e7a522b52816f05a75dcc7366628ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 11 Nov 2024 16:57:00 +0100 Subject: [PATCH 05/30] feat(initialization): enhance documentation --- .../server/services/initialization/README.md | 53 +++++++++++++++++-- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/plugins/wazuh-core/server/services/initialization/README.md b/plugins/wazuh-core/server/services/initialization/README.md index ae894e95f3..a2f0cee064 100644 --- a/plugins/wazuh-core/server/services/initialization/README.md +++ b/plugins/wazuh-core/server/services/initialization/README.md @@ -8,6 +8,18 @@ The tasks run on parallel. Optionally the registered tasks could be retrieved to run in API endpoints or getting information about its status. +There are 2 scopes: + +- `internal`: run through the internal user + - on plugin starts + - on demand +- `user`: run through the logged (requester) user + - on demand + +The scopes can be used to get a specific context (clients, parameters) that is set in the `scope` property of the task context. + +The `internal` scoped tasks keep the same execution data (see [Task execution data](#task-execution-data)), and the `user` scoped task are newly created on demand. + # InitializationService tasks A task can be defined with: @@ -32,6 +44,24 @@ server log [11:57:39.648] [info][index-pattern-vulnerabilities-states][init the task name is `index-pattern-vulnerabilities-states`. +## Task name convention + +- lowercase +- kebab case (`word1-word2`) +- use colon ( `:` ) for tasks related to some entity that have different subentities. + +``` +entity_identifier:entity_specific +``` + +For example: + +``` +index-pattern:alerts +index-pattern:statistics +index-pattern:vulnerabilities-states +``` + ## Register a task ```ts @@ -39,7 +69,7 @@ the task name is `index-pattern-vulnerabilities-states`. setup(){ // Register a task - plugins.wazuhCore.register({ + plugins.wazuhCore.initialization.register({ name: 'custom-task', run: (ctx) => { console.log('Run from wazuhCore starts' ) @@ -49,18 +79,31 @@ setup(){ } ``` -## Task data +## Task execution data The task has the following data related to the execution: ```ts interface InitializationTaskRunData { + name: string; status: 'not_started' | 'running' | 'finished'; result: 'success' | 'fail'; - startAt: number | null; - endAt: number | null; - duration: number | null; + createdAt: string | null; + startedAt: string | null; + finishedAt: string | null; + duration: number | null; // seconds data: any; error: string | null; } ``` + +## Create a task instance + +This is used to create the user scoped tasks. + +```ts +const newTask = + context.wazuh_core.initialization.createNewTaskFromRegisteredTask( + 'example-task', + ); +``` From c5aaf7c5d2b3b51263eef3b51e87c1f7f2b74602 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 12 Nov 2024 12:53:12 +0100 Subject: [PATCH 06/30] feat(initialization): add tests - Add tests - Enhance tasks error logging - Fix minor problems --- .../lib/initialization/index-patterns.ts | 8 +- .../server/lib/initialization/settings.ts | 4 +- .../server/lib/initialization/templates.ts | 7 +- .../server/initialization/server-api.test.ts | 71 +++++++++++++++- .../server/initialization/server-api.ts | 82 +++++++++++-------- 5 files changed, 130 insertions(+), 42 deletions(-) diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/main/server/lib/initialization/index-patterns.ts index 083cd8e018..f0f7cfaba3 100644 --- a/plugins/main/server/lib/initialization/index-patterns.ts +++ b/plugins/main/server/lib/initialization/index-patterns.ts @@ -52,7 +52,7 @@ export const ensureIndexPatternExistence = async ( ); } else { throw new Error( - `Error checking the existence of index pattern with ID [${indexPatternID}]: ${e.message}`, + `index pattern with ID [${indexPatternID}] existence could not be checked due to: ${e.message}`, ); } } @@ -128,7 +128,7 @@ async function createIndexPattern( return response; } catch (e) { throw new Error( - `Error creating index pattern with ID [${indexPatternID}]: ${e.message}`, + `index pattern with ID [${indexPatternID}] could not be created due to: ${e.message}`, ); } } @@ -208,7 +208,9 @@ export const initializationTaskCreatorIndexPattern = ({ }, ); } catch (e) { - throw new Error(`Error initilizating index pattern ${e.message}`); + const message = `Error initilizating index pattern with ID [${indexPatternID}]: ${e.message}`; + ctx.logger.error(message); + throw new Error(message); } }, }); diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts index 58f41d374b..84c0b83a61 100644 --- a/plugins/main/server/lib/initialization/settings.ts +++ b/plugins/main/server/lib/initialization/settings.ts @@ -174,7 +174,9 @@ export const initializationTaskCreatorSetting = ( ); ctx.logger.info('Start setting finished'); } catch (e) { - throw new Error(`Error initilizating setting ${e.message}`); + const message = `Error initilizating setting [${setting.key}]: ${e.message}`; + ctx.logger.error(message); + throw new Error(message); } }, }); diff --git a/plugins/main/server/lib/initialization/templates.ts b/plugins/main/server/lib/initialization/templates.ts index 8030fea615..4315c186d3 100644 --- a/plugins/main/server/lib/initialization/templates.ts +++ b/plugins/main/server/lib/initialization/templates.ts @@ -71,18 +71,21 @@ export const initializationTaskCreatorExistTemplate = ({ }) => ({ name: taskName, async run(ctx) { + let indexPatternTitle; try { ctx.logger.debug('Starting check of existent template'); const opensearchClient = getOpenSearchClient(ctx); - const indexPatternTitle = await getIndexPatternTitle(ctx); + indexPatternTitle = await getIndexPatternTitle(ctx); await checkIndexPatternHasTemplate(ctx, { opensearchClient, indexPatternTitle, }); ctx.logger.info('Start check of existent template finished'); } catch (e) { - ctx.logger.error(`Error checking of existent template: ${e.message}`); + const message = `Error checking of existent template for index pattern with title [${indexPatternTitle}]: ${e.message}`; + ctx.logger.error(message); + throw new Error(message); } }, }); diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index d8b4b93b34..bc9d56667b 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -1,4 +1,13 @@ -import { checkAppServerCompatibility } from './server-api'; +import { + PLUGIN_APP_NAME, + PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, +} from '../../common/constants'; +import { webDocumentationLink } from '../../common/services/web_documentation'; +import { version as appVersion } from '../../package.json'; +import { + ServerAPIConnectionCompatibility, + checkAppServerCompatibility, +} from './server-api'; describe('checkAppServerCompatibility', () => { it.each` @@ -25,3 +34,63 @@ describe('checkAppServerCompatibility', () => { }, ); }); + +describe('ServerAPIConnectionCompatibility', () => { + it.each` + apiHostID | apiVersionResponse | isCompatible + ${'server1'} | ${{ api_version: '5.0.0' }} | ${true} + ${'server2'} | ${{ api_version: '0.0.0' }} | ${false} + ${'server3'} | ${{ missing_api_version_field: null }} | ${false} + `( + `Check server API connection and compatibility for the server API hosts`, + async ({ apiHostID, apiVersionResponse, isCompatible }) => { + const loggerMock = jest.fn(); + const result = await ServerAPIConnectionCompatibility( + { + manageHosts: { + get: () => hosts, + }, + logger: { + debug: loggerMock, + info: loggerMock, + warn: loggerMock, + error: loggerMock, + }, + serverAPIClient: { + asInternalUser: { + request: () => ({ + data: { + data: apiVersionResponse, + }, + }), + }, + }, + }, + apiHostID, + appVersion, + ); + expect(loggerMock).toHaveBeenCalledWith( + `Checking the connection and compatibility with server API [${apiHostID}]`, + ); + if (apiVersionResponse.api_version) { + if (isCompatible === true) { + expect(loggerMock).toHaveBeenCalledWith( + `Server API [${apiHostID}] version [${apiVersionResponse.api_version}] is compatible with the ${PLUGIN_APP_NAME} version`, + ); + } else if (isCompatible === false) { + expect(loggerMock).toHaveBeenCalledWith( + `Server API [${apiHostID}] version [${ + apiVersionResponse.api_version + }] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( + PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, + )}.`, + ); + } + } else { + expect(loggerMock).toHaveBeenCalledWith( + `Error checking the connection and compatibility with server API [${apiHostID}]: version is not found in the response of server API`, + ); + } + }, + ); +}); diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index da1a5a38a0..f04e8eec46 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -16,58 +16,70 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ ctx.logger.debug( 'Starting check server API connection and compatibility', ); - await ServerAPIConnectionCompatibility(ctx); + await ServersAPIConnectionCompatibility(ctx); ctx.logger.info( 'Start check server API connection and compatibility finished', ); } catch (e) { - ctx.logger.error( - `Error checking server API connection and compatibility: ${e.message}`, - ); + const message = `Error checking server API connection and compatibility: ${e.message}`; + ctx.logger.error(message); + throw new Error(message); } }, }); -export async function ServerAPIConnectionCompatibility(ctx) { +async function ServersAPIConnectionCompatibility(ctx) { const hosts = await ctx.manageHosts.get(undefined, { excludePassword: true, }); ctx.logger.debug(`APP version [${appVersion}]`); - await Promise.all( - hosts.map(async ({ id: apiHostID }) => { - try { - ctx.logger.debug( - `Checking the connection and compatibility with server API [${apiHostID}]`, - ); - const response = await ctx.serverAPIClient.asInternalUser.request( - 'GET', - '/', - {}, - { apiHostID }, - ); - const { api_version: serverAPIVersion } = response?.data?.data; - if (!serverAPIVersion) { - throw new Error('version is not found in the response of server API'); - } - ctx.logger.debug(`Server API version [${serverAPIVersion}]`); - if (!checkAppServerCompatibility(appVersion, serverAPIVersion)) { - ctx.logger.warn( - `Server API version [${serverAPIVersion}] is not compatible with the ${PLUGIN_APP_NAME} version [${apiVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( - PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, - )}.`, - ); - } - } catch (e) { - ctx.logger.error( - `Error checking the connection and compatibility with server API [${apiHostID}]: ${e.message}`, - ); - } - }), + return await Promise.all( + hosts.map(async ({ id: apiHostID }: { id: string }) => + ServerAPIConnectionCompatibility(ctx, apiHostID, appVersion), + ), ); } +export async function ServerAPIConnectionCompatibility( + ctx: any, + apiHostID: string, + appVersion: string, +) { + try { + ctx.logger.debug( + `Checking the connection and compatibility with server API [${apiHostID}]`, + ); + const response = await ctx.serverAPIClient.asInternalUser.request( + 'GET', + '/', + {}, + { apiHostID }, + ); + const { api_version: serverAPIVersion } = response?.data?.data; + if (!serverAPIVersion) { + throw new Error('version is not found in the response of server API'); + } + ctx.logger.debug(`Server API version [${serverAPIVersion}]`); + if (!checkAppServerCompatibility(appVersion, serverAPIVersion)) { + ctx.logger.warn( + `Server API [${apiHostID}] version [${serverAPIVersion}] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( + PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, + )}.`, + ); + return; + } + ctx.logger.info( + `Server API [${apiHostID}] version [${serverAPIVersion}] is compatible with the ${PLUGIN_APP_NAME} version`, + ); + } catch (e) { + ctx.logger.warn( + `Error checking the connection and compatibility with server API [${apiHostID}]: ${e.message}`, + ); + } +} + export function checkAppServerCompatibility(appVersion, serverAPIVersion) { const api = /v?(?\d+)\.(?\d+)\.(?\d+)/.exec( serverAPIVersion, From 4c0a8632a711d24b475a58bc7f90c4c5189c25e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 12 Nov 2024 16:46:33 +0100 Subject: [PATCH 07/30] feat(initialization): enhance task related to check connection and compatibility with server API --- .../server/initialization/server-api.ts | 62 +++++++++++++------ 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index f04e8eec46..7aab23626e 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -16,10 +16,11 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ ctx.logger.debug( 'Starting check server API connection and compatibility', ); - await ServersAPIConnectionCompatibility(ctx); + const results = await ServersAPIConnectionCompatibility(ctx); ctx.logger.info( 'Start check server API connection and compatibility finished', ); + return results; } catch (e) { const message = `Error checking server API connection and compatibility: ${e.message}`; ctx.logger.error(message); @@ -29,17 +30,27 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ }); async function ServersAPIConnectionCompatibility(ctx) { - const hosts = await ctx.manageHosts.get(undefined, { - excludePassword: true, - }); + if (ctx.scope === 'user' && ctx.request?.query?.apiHostID) { + const host = await ctx.manageHosts.get(ctx.request.query.apiHostID, { + excludePassword: true, + }); - ctx.logger.debug(`APP version [${appVersion}]`); + ctx.logger.debug(`APP version [${appVersion}]`); - return await Promise.all( - hosts.map(async ({ id: apiHostID }: { id: string }) => - ServerAPIConnectionCompatibility(ctx, apiHostID, appVersion), - ), - ); + return await ServerAPIConnectionCompatibility(ctx, host.id, appVersion); + } else { + const hosts = await ctx.manageHosts.get(undefined, { + excludePassword: true, + }); + + ctx.logger.debug(`APP version [${appVersion}]`); + + return await Promise.all( + hosts.map(async ({ id: apiHostID }: { id: string }) => + ServerAPIConnectionCompatibility(ctx, apiHostID, appVersion), + ), + ); + } } export async function ServerAPIConnectionCompatibility( @@ -47,6 +58,9 @@ export async function ServerAPIConnectionCompatibility( apiHostID: string, appVersion: string, ) { + let connection = null, + compatibility = null, + api_version = null; try { ctx.logger.debug( `Checking the connection and compatibility with server API [${apiHostID}]`, @@ -57,30 +71,38 @@ export async function ServerAPIConnectionCompatibility( {}, { apiHostID }, ); - const { api_version: serverAPIVersion } = response?.data?.data; - if (!serverAPIVersion) { + connection = true; + api_version = response?.data?.data?.api_version; + if (!api_version) { throw new Error('version is not found in the response of server API'); } - ctx.logger.debug(`Server API version [${serverAPIVersion}]`); - if (!checkAppServerCompatibility(appVersion, serverAPIVersion)) { + ctx.logger.debug(`Server API version [${api_version}]`); + if (!checkAppServerCompatibility(appVersion, api_version)) { + compatibility = false; ctx.logger.warn( - `Server API [${apiHostID}] version [${serverAPIVersion}] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( + `Server API [${apiHostID}] version [${api_version}] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, )}.`, ); - return; + } else { + compatibility = true; + ctx.logger.info( + `Server API [${apiHostID}] version [${api_version}] is compatible with the ${PLUGIN_APP_NAME} version`, + ); } - ctx.logger.info( - `Server API [${apiHostID}] version [${serverAPIVersion}] is compatible with the ${PLUGIN_APP_NAME} version`, - ); } catch (e) { ctx.logger.warn( `Error checking the connection and compatibility with server API [${apiHostID}]: ${e.message}`, ); + } finally { + return { connection, compatibility, api_version, id: apiHostID }; } } -export function checkAppServerCompatibility(appVersion, serverAPIVersion) { +export function checkAppServerCompatibility( + appVersion: string, + serverAPIVersion: string, +) { const api = /v?(?\d+)\.(?\d+)\.(?\d+)/.exec( serverAPIVersion, ); From d5b0b9fe77077c4552d26cf788bb729554062a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 12 Nov 2024 16:47:39 +0100 Subject: [PATCH 08/30] fix(initialization): minor fixes in tasks --- plugins/main/server/lib/initialization/index-patterns.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/main/server/lib/initialization/index-patterns.ts index f0f7cfaba3..230cc71d5a 100644 --- a/plugins/main/server/lib/initialization/index-patterns.ts +++ b/plugins/main/server/lib/initialization/index-patterns.ts @@ -94,7 +94,7 @@ async function createIndexPattern( indexPatternID, ); } catch (e) { - if (options.fieldsNoIndices) { + if (e?.output?.statusCode === 404 && options.fieldsNoIndices) { const message = `Fields for index pattern with ID [${indexPatternID}] could not be obtained. This could indicate there are not matching indices because they were not generated or there is some error in the process that generates and indexes that data. The index pattern will be created with a set of pre-defined fields.`; logger.warn(message); fields = options.fieldsNoIndices; @@ -152,7 +152,7 @@ function getIndexPatternsClient(ctx: any, scope) { switch (scope) { case 'internal': return new IndexPatternsFetcher( - ctx.core.opensearch.legacy.client.callAsCurrentUser, + ctx.core.opensearch.legacy.client.callAsInternalUser, ); break; case 'user': @@ -191,9 +191,10 @@ export const initializationTaskCreatorIndexPattern = ({ }) => ({ name: taskName, async run(ctx) { + let indexPatternID; try { ctx.logger.debug('Starting index pattern saved object'); - const indexPatternID = await getIndexPatternID(ctx, ctx.scope, rest); + indexPatternID = await getIndexPatternID(ctx, ctx.scope, rest); // Get clients depending on the scope const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); From 1b052be6f5f2f25164db32c2139f7f2456a0794f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 12 Nov 2024 16:48:30 +0100 Subject: [PATCH 09/30] feat(initialization): add default fields for vulnerability-states index pattern --- .../utils/vulnerabibility-states-fields.json | 515 ++++++++++++++++++ plugins/main/server/plugin.ts | 3 +- 2 files changed, 517 insertions(+), 1 deletion(-) create mode 100644 plugins/main/public/utils/vulnerabibility-states-fields.json diff --git a/plugins/main/public/utils/vulnerabibility-states-fields.json b/plugins/main/public/utils/vulnerabibility-states-fields.json new file mode 100644 index 0000000000..216cfdc68f --- /dev/null +++ b/plugins/main/public/utils/vulnerabibility-states-fields.json @@ -0,0 +1,515 @@ +[ + { + "count": 0, + "name": "_index", + "type": "string", + "esTypes": ["_index"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "count": 0, + "name": "_source", + "type": "_source", + "esTypes": ["_source"], + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "agent.build.original", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "agent.ephemeral_id", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "agent.id", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "agent.name", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "agent.type", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "agent.version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.family", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.full", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.full.text", + "type": "string", + "esTypes": ["text"], + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false, + "subType": { "multi": { "parent": "host.os.full" } } + }, + { + "count": 0, + "name": "host.os.kernel", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.name", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.name.text", + "type": "string", + "esTypes": ["text"], + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false, + "subType": { "multi": { "parent": "host.os.name" } } + }, + { + "count": 0, + "name": "host.os.platform", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.type", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "host.os.version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "message", + "type": "string", + "esTypes": ["text"], + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "count": 0, + "name": "package.architecture", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.build_version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.checksum", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.description", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.install_scope", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.installed", + "type": "date", + "esTypes": ["date"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.license", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.name", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.path", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.reference", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.size", + "type": "number", + "esTypes": ["long"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.type", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "package.version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "tags", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.category", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.classification", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.description", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.description.text", + "type": "string", + "esTypes": ["text"], + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false, + "subType": { "multi": { "parent": "vulnerability.description" } } + }, + { + "count": 0, + "name": "vulnerability.detected_at", + "type": "date", + "esTypes": ["date"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.enumeration", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.id", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.published_at", + "type": "date", + "esTypes": ["date"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.reference", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.report_id", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.scanner.vendor", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.score.base", + "type": "number", + "esTypes": ["float"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.score.environmental", + "type": "number", + "esTypes": ["float"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.score.temporal", + "type": "number", + "esTypes": ["float"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.score.version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "vulnerability.severity", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "wazuh.cluster.name", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "wazuh.cluster.node", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "count": 0, + "name": "wazuh.schema.version", + "type": "string", + "esTypes": ["keyword"], + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + } +] diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index 31983be561..a9d74d5db6 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -53,6 +53,7 @@ import { import { KnownFields } from '../public/utils/known-fields'; import { FieldsStatistics } from '../public/utils/statistics-fields'; import { FieldsMonitoring } from '../public/utils/monitoring-fields'; +import VulnerabilitiesStatesFields from '../public/utils/vulnerabibility-states-fields.json'; declare module 'opensearch_dashboards/server' { interface RequestHandlerContext { @@ -165,7 +166,7 @@ export class WazuhPlugin implements Plugin { ctx.configuration.get('vulnerabilities.pattern'), taskName: 'index-pattern:vulnerabilities-states', options: { - // fieldsNoIndices: JSON.stringify(FieldsStatistics), // TODO: add fallback fields + fieldsNoIndices: VulnerabilitiesStatesFields, }, configurationSettingKey: 'checks.monitoring', }), From fb4eb7f799a8ed800f4b186d24f3e22871a58b23 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 22 Nov 2024 16:04:00 +0100 Subject: [PATCH 10/30] fix: import statement related to specific function instead of all module --- plugins/main/server/lib/initialization/settings.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts index 84c0b83a61..8cfbe62433 100644 --- a/plugins/main/server/lib/initialization/settings.ts +++ b/plugins/main/server/lib/initialization/settings.ts @@ -12,7 +12,7 @@ * */ -import _ from 'lodash'; +import { isEqual } from 'lodash'; const decoratorCheckIsEnabled = fn => { return async ( @@ -42,7 +42,7 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( const valuePluginPlatformSetting = await uiSettingsClient.get( pluginPlatformSettingName, ); - const settingsAreDifferent = !_.isEqual( + const settingsAreDifferent = !isEqual( valuePluginPlatformSetting, defaultAppValue, ); From 59205474021c2c898e731d851ab23f102066ba52 Mon Sep 17 00:00:00 2001 From: Antonio <34042064+Desvelao@users.noreply.github.com> Date: Fri, 22 Nov 2024 16:20:06 +0100 Subject: [PATCH 11/30] Apply suggestions from code review Co-authored-by: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> --- plugins/main/server/lib/initialization/settings.ts | 4 ---- .../server/initialization/server-api.test.ts | 2 +- .../wazuh-core/server/initialization/server-api.ts | 8 ++++---- .../services/initialization/initialization.ts | 2 ++ .../server/services/initialization/routes.ts | 2 +- .../server/services/initialization/types.ts | 13 ++++++------- plugins/wazuh-core/server/services/types.ts | 12 ++++++------ 7 files changed, 20 insertions(+), 23 deletions(-) diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/main/server/lib/initialization/settings.ts index 8cfbe62433..3ee6ff3990 100644 --- a/plugins/main/server/lib/initialization/settings.ts +++ b/plugins/main/server/lib/initialization/settings.ts @@ -115,12 +115,10 @@ function getSavedObjectsClient(ctx: any, scope) { switch (scope) { case 'internal': return ctx.core.savedObjects.createInternalRepository(); - break; case 'user': return ctx.core.savedObjects.savedObjectsStart.getScopedClient( ctx.request, ); - break; default: break; } @@ -130,11 +128,9 @@ function getUiSettingsClient(ctx, scope, client) { switch (scope) { case 'internal': return ctx.core.uiSettings.asScopedToClient(client); - break; case 'user': return ctx.core.uiSettings.uiSettingsStart.asScopedToClient(client); - break; default: break; diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index bc9d56667b..c0d4ffa4d7 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -45,7 +45,7 @@ describe('ServerAPIConnectionCompatibility', () => { `Check server API connection and compatibility for the server API hosts`, async ({ apiHostID, apiVersionResponse, isCompatible }) => { const loggerMock = jest.fn(); - const result = await ServerAPIConnectionCompatibility( + await ServerAPIConnectionCompatibility( { manageHosts: { get: () => hosts, diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index 7aab23626e..843c4449c0 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -21,8 +21,8 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ 'Start check server API connection and compatibility finished', ); return results; - } catch (e) { - const message = `Error checking server API connection and compatibility: ${e.message}`; + } catch (error) { + const message = `Error checking server API connection and compatibility: ${error.message}`; ctx.logger.error(message); throw new Error(message); } @@ -90,9 +90,9 @@ export async function ServerAPIConnectionCompatibility( `Server API [${apiHostID}] version [${api_version}] is compatible with the ${PLUGIN_APP_NAME} version`, ); } - } catch (e) { + } catch (error) { ctx.logger.warn( - `Error checking the connection and compatibility with server API [${apiHostID}]: ${e.message}`, + `Error checking the connection and compatibility with server API [${apiHostID}]: ${error.message}`, ); } finally { return { connection, compatibility, api_version, id: apiHostID }; diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index d79531b9e3..96913f9bc6 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -47,6 +47,8 @@ export class InitializationService implements IInitializationService { if (name) { return this.items.get(name); } + } + getAll() { return Array.from(this.items.values()); } createRunContext(scope: InitializationTaskContext, context: any = {}) { diff --git a/plugins/wazuh-core/server/services/initialization/routes.ts b/plugins/wazuh-core/server/services/initialization/routes.ts index cf7e523827..568e0353a1 100644 --- a/plugins/wazuh-core/server/services/initialization/routes.ts +++ b/plugins/wazuh-core/server/services/initialization/routes.ts @@ -42,7 +42,7 @@ export function addRoutes(router, { initialization }) { ? tasksNames.map(taskName => context.wazuh_core.initialization.get(taskName), ) - : context.wazuh_core.initialization.get(); + : context.wazuh_core.initialization.getAll(); const tasksData = tasks.map(task => task.getInfo()); diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index e08faee1f4..717636e206 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -18,7 +18,7 @@ export interface InitializationTaskRunData { } export interface IInitializationTask extends InitializationTaskRunData { - run(ctx: any): Promise; + run(ctx: Context): Promise; getInfo(): InitializationTaskRunData; } @@ -26,14 +26,13 @@ export type InitializationTaskContext = 'internal' | 'user'; export interface IInitializationService extends LifecycleService { register(task: InitializationTaskDefinition): void; - get( - taskName?: string, - ): InitializationTaskRunData | InitializationTaskRunData[]; - createRunContext( + get(taskName?: string): InitializationTaskRunData; + getAll(): InitializationTaskRunData[]; + createRunContext( scope: InitializationTaskContext, - context: any, + context: ContextType, ): { scope: InitializationTaskContext; }; - runAsInternal(tasks?: string[]): Promise; + runAsInternal(tasks?: string[]): Promise; } diff --git a/plugins/wazuh-core/server/services/types.ts b/plugins/wazuh-core/server/services/types.ts index bb6c43c39f..75147d110f 100644 --- a/plugins/wazuh-core/server/services/types.ts +++ b/plugins/wazuh-core/server/services/types.ts @@ -1,10 +1,10 @@ export interface LifecycleService< - SetupDeps, - SetupReturn, - StartDeps, - StartReturn, - StopDeps, - StopReturn, + SetupDeps = any, + SetupReturn = any, + StartDeps = any, + StartReturn = any, + StopDeps = any, + StopReturn = any, > { setup: (deps: SetupDeps) => SetupReturn; start: (deps: StartDeps) => StartReturn; From a68e03d315f60d605b30626ed073c14f8d3f0c89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 22 Nov 2024 16:47:15 +0100 Subject: [PATCH 12/30] fix: rename setting --- plugins/main/server/plugin.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index a9d74d5db6..a52ece8d54 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -155,7 +155,7 @@ export class WazuhPlugin implements Plugin { }, fieldsNoIndices: FieldsMonitoring, }, - configurationSettingKey: 'checks.monitoring', + configurationSettingKey: 'checks.monitoring', // TODO: create new setting }), ); // Index pattern: vulnerabilities @@ -168,7 +168,7 @@ export class WazuhPlugin implements Plugin { options: { fieldsNoIndices: VulnerabilitiesStatesFields, }, - configurationSettingKey: 'checks.monitoring', + configurationSettingKey: 'checks.vulnerability', // TODO: create new setting }), ); @@ -194,7 +194,7 @@ export class WazuhPlugin implements Plugin { }, fieldsNoIndices: FieldsStatistics, }, - configurationSettingKey: 'checks.statistics', + configurationSettingKey: 'checks.statistics', // TODO: create new setting }), ); From 409115f401aa99626f39a88bf20fc963b1d61f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 25 Nov 2024 15:43:47 +0100 Subject: [PATCH 13/30] fix(initialization): apply review suggestions related to creation of constants --- .../services/initialization/constants.ts | 9 ++++++ .../common/services/initialization/types.ts | 21 ++++++++++++++ .../services/initialization/initialization.ts | 29 ++++++++++++++----- .../server/services/initialization/types.ts | 10 +++++-- 4 files changed, 58 insertions(+), 11 deletions(-) create mode 100644 plugins/wazuh-core/common/services/initialization/constants.ts create mode 100644 plugins/wazuh-core/common/services/initialization/types.ts diff --git a/plugins/wazuh-core/common/services/initialization/constants.ts b/plugins/wazuh-core/common/services/initialization/constants.ts new file mode 100644 index 0000000000..90a9c27228 --- /dev/null +++ b/plugins/wazuh-core/common/services/initialization/constants.ts @@ -0,0 +1,9 @@ +export const INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED = 'not_started'; +export const INITIALIZATION_TASK_RUN_STATUS_RUNNING = 'running'; +export const INITIALIZATION_TASK_RUN_STATUS_FINISHED = 'finished'; +export const INITIALIZATION_TASK_RUN_RESULT_NULL = null; +export const INITIALIZATION_TASK_RUN_RESULT_SUCCESS = 'success'; +export const INITIALIZATION_TASK_RUN_RESULT_FAIL = 'fail'; + +export const INITIALIZATION_TASK_CONTEXT_INTERNAL = 'internal'; +export const INITIALIZATION_TASK_CONTEXT_USER = 'user'; diff --git a/plugins/wazuh-core/common/services/initialization/types.ts b/plugins/wazuh-core/common/services/initialization/types.ts new file mode 100644 index 0000000000..2b4e2d164d --- /dev/null +++ b/plugins/wazuh-core/common/services/initialization/types.ts @@ -0,0 +1,21 @@ +export type InitializationTaskRunStatusNotStarted = 'not_started'; +export type InitializationTaskRunStatusRunning = 'running'; +export type InitializationTaskRunStatusFinished = 'finished'; +export type InitializationTaskRunStatus = + | InitializationTaskRunStatusNotStarted + | InitializationTaskRunStatusRunning + | InitializationTaskRunStatusFinished; + +export type InitializationTaskRunResultNull = null; +export type InitializationTaskRunResultSuccess = 'success'; +export type InitializationTaskRunResultFail = 'fail'; +export type InitializationTaskRunResult = + | InitializationTaskRunResultSuccess + | InitializationTaskRunResultFail + | InitializationTaskRunResultNull; + +export type InitializationTaskContextInternal = 'internal'; +export type InitializationTaskContextUser = 'user'; +export type InitializationTaskContext = + | InitializationTaskContextInternal + | InitializationTaskContextUser; diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index 96913f9bc6..e7c705f6c1 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -7,6 +7,15 @@ import { InitializationTaskContext, } from './types'; import { addRoutes } from './routes'; +import { + INITIALIZATION_TASK_CONTEXT_INTERNAL, + INITIALIZATION_TASK_RUN_RESULT_FAIL, + INITIALIZATION_TASK_RUN_RESULT_NULL, + INITIALIZATION_TASK_RUN_RESULT_SUCCESS, + INITIALIZATION_TASK_RUN_STATUS_FINISHED, + INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED, + INITIALIZATION_TASK_RUN_STATUS_RUNNING, +} from '../../../common/services/initialization/constants'; export class InitializationService implements IInitializationService { private items: Map; @@ -55,7 +64,9 @@ export class InitializationService implements IInitializationService { return { ...this.services, ...context, scope }; } async runAsInternal(taskNames?: string[]) { - const ctx = this.createRunContext('internal', { core: this._coreStart }); + const ctx = this.createRunContext(INITIALIZATION_TASK_CONTEXT_INTERNAL, { + core: this._coreStart, + }); return await this.run(ctx, taskNames); } createNewTaskFromRegisteredTask(name: string) { @@ -103,8 +114,10 @@ export class InitializationService implements IInitializationService { class InitializationTask implements IInitializationTask { public name: string; private _run: any; - public status: InitializationTaskRunData['status'] = 'not_started'; - public result: InitializationTaskRunData['result'] = null; + public status: InitializationTaskRunData['status'] = + INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED; + public result: InitializationTaskRunData['result'] = + INITIALIZATION_TASK_RUN_RESULT_NULL; public data: any = null; public createdAt: InitializationTaskRunData['createdAt'] = new Date().toISOString(); @@ -117,7 +130,7 @@ class InitializationTask implements IInitializationTask { this._run = task.run; } private init() { - this.status = 'running'; + this.status = INITIALIZATION_TASK_RUN_STATUS_RUNNING; this.result = null; this.data = null; this.startedAt = new Date().toISOString(); @@ -126,20 +139,20 @@ class InitializationTask implements IInitializationTask { this.error = null; } async run(...params) { - if (this.status === 'running') { + if (this.status === INITIALIZATION_TASK_RUN_STATUS_RUNNING) { throw new Error(`Another instance of task ${this.name} is running`); } let error; try { this.init(); this.data = await this._run(...params); - this.result = 'success'; + this.result = INITIALIZATION_TASK_RUN_RESULT_SUCCESS; } catch (e) { error = e; - this.result = 'fail'; + this.result = INITIALIZATION_TASK_RUN_RESULT_FAIL; this.error = e.message; } finally { - this.status = 'finished'; + this.status = INITIALIZATION_TASK_RUN_STATUS_FINISHED; this.finishedAt = new Date().toISOString(); const dateStartedAt = new Date(this.startedAt!); const dateFinishedAt = new Date(this.finishedAt); diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index 717636e206..bbb51eb079 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -1,3 +1,7 @@ +import { + InitializationTaskRunResult, + InitializationTaskRunStatus, +} from '../../../common/services/initialization/types'; import { LifecycleService } from '../types'; export interface InitializationTaskDefinition { @@ -7,8 +11,8 @@ export interface InitializationTaskDefinition { export interface InitializationTaskRunData { name: InitializationTaskDefinition['name']; - status: 'not_started' | 'running' | 'finished'; - result: 'success' | 'fail' | null; + status: InitializationTaskRunStatus; + result: InitializationTaskRunResult; createdAt: string | null; startedAt: string | null; finishedAt: string | null; @@ -27,7 +31,7 @@ export interface IInitializationService extends LifecycleService { register(task: InitializationTaskDefinition): void; get(taskName?: string): InitializationTaskRunData; - getAll(): InitializationTaskRunData[]; + getAll(): InitializationTaskRunData[]; createRunContext( scope: InitializationTaskContext, context: ContextType, From d123f3144ab5361bb1009dfeb0247302f6784e25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 25 Nov 2024 16:50:28 +0100 Subject: [PATCH 14/30] fix(initialization): move InitializationTask class to another file --- .../services/initialization/initialization.ts | 97 ++----------------- .../initialization/lib/initialization-task.ts | 87 +++++++++++++++++ .../server/services/initialization/types.ts | 2 +- 3 files changed, 96 insertions(+), 90 deletions(-) create mode 100644 plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index e7c705f6c1..95cbe18ba0 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -2,20 +2,11 @@ import { Logger } from 'opensearch-dashboards/server'; import { InitializationTaskDefinition, IInitializationService, - InitializationTaskRunData, - IInitializationTask, InitializationTaskContext, } from './types'; import { addRoutes } from './routes'; -import { - INITIALIZATION_TASK_CONTEXT_INTERNAL, - INITIALIZATION_TASK_RUN_RESULT_FAIL, - INITIALIZATION_TASK_RUN_RESULT_NULL, - INITIALIZATION_TASK_RUN_RESULT_SUCCESS, - INITIALIZATION_TASK_RUN_STATUS_FINISHED, - INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED, - INITIALIZATION_TASK_RUN_STATUS_RUNNING, -} from '../../../common/services/initialization/constants'; +import { INITIALIZATION_TASK_CONTEXT_INTERNAL } from '../../../common/services/initialization/constants'; +import { InitializationTask } from './lib/initialization-task'; export class InitializationService implements IInitializationService { private items: Map; @@ -51,13 +42,15 @@ export class InitializationService implements IInitializationService { this.items.set(task.name, new InitializationTask(task)); this.logger.debug(`Registered ${task.name}`); } - get(name?: string) { - this.logger.debug(`Getting tasks: ${name ? `[${name}]` : ''}`); - if (name) { - return this.items.get(name); + get(name: string) { + this.logger.debug(`Getting task: [${name}]`); + if (!this.items.has(name)) { + throw new Error(`Task [${name}] not found`); } + return this.items.get(name); } getAll() { + this.logger.debug('Getting all tasks'); return Array.from(this.items.values()); } createRunContext(scope: InitializationTaskContext, context: any = {}) { @@ -110,77 +103,3 @@ export class InitializationService implements IInitializationService { } } } - -class InitializationTask implements IInitializationTask { - public name: string; - private _run: any; - public status: InitializationTaskRunData['status'] = - INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED; - public result: InitializationTaskRunData['result'] = - INITIALIZATION_TASK_RUN_RESULT_NULL; - public data: any = null; - public createdAt: InitializationTaskRunData['createdAt'] = - new Date().toISOString(); - public startedAt: InitializationTaskRunData['startedAt'] = null; - public finishedAt: InitializationTaskRunData['finishedAt'] = null; - public duration: InitializationTaskRunData['duration'] = null; - public error = null; - constructor(task: InitializationTaskDefinition) { - this.name = task.name; - this._run = task.run; - } - private init() { - this.status = INITIALIZATION_TASK_RUN_STATUS_RUNNING; - this.result = null; - this.data = null; - this.startedAt = new Date().toISOString(); - this.finishedAt = null; - this.duration = null; - this.error = null; - } - async run(...params) { - if (this.status === INITIALIZATION_TASK_RUN_STATUS_RUNNING) { - throw new Error(`Another instance of task ${this.name} is running`); - } - let error; - try { - this.init(); - this.data = await this._run(...params); - this.result = INITIALIZATION_TASK_RUN_RESULT_SUCCESS; - } catch (e) { - error = e; - this.result = INITIALIZATION_TASK_RUN_RESULT_FAIL; - this.error = e.message; - } finally { - this.status = INITIALIZATION_TASK_RUN_STATUS_FINISHED; - this.finishedAt = new Date().toISOString(); - const dateStartedAt = new Date(this.startedAt!); - const dateFinishedAt = new Date(this.finishedAt); - this.duration = ((dateFinishedAt - dateStartedAt) as number) / 1000; - } - if (error) { - throw error; - } - return this.getInfo(); - } - - getInfo() { - return [ - 'name', - 'status', - 'result', - 'data', - 'createdAt', - 'startedAt', - 'finishedAt', - 'duration', - 'error', - ].reduce( - (accum, item) => ({ - ...accum, - [item]: this[item], - }), - {}, - ) as IInitializationTask; - } -} diff --git a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts new file mode 100644 index 0000000000..166d294e45 --- /dev/null +++ b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts @@ -0,0 +1,87 @@ +import { + InitializationTaskDefinition, + InitializationTaskRunData, + IInitializationTask, +} from '../types'; +import { + INITIALIZATION_TASK_RUN_RESULT_FAIL, + INITIALIZATION_TASK_RUN_RESULT_NULL, + INITIALIZATION_TASK_RUN_RESULT_SUCCESS, + INITIALIZATION_TASK_RUN_STATUS_FINISHED, + INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED, + INITIALIZATION_TASK_RUN_STATUS_RUNNING, +} from '../../../../common/services/initialization/constants'; + +export class InitializationTask implements IInitializationTask { + public name: string; + private _run: any; + public status: InitializationTaskRunData['status'] = + INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED; + public result: InitializationTaskRunData['result'] = + INITIALIZATION_TASK_RUN_RESULT_NULL; + public data: any = null; + public createdAt: InitializationTaskRunData['createdAt'] = + new Date().toISOString(); + public startedAt: InitializationTaskRunData['startedAt'] = null; + public finishedAt: InitializationTaskRunData['finishedAt'] = null; + public duration: InitializationTaskRunData['duration'] = null; + public error = null; + constructor(task: InitializationTaskDefinition) { + this.name = task.name; + this._run = task.run; + } + private init() { + this.status = INITIALIZATION_TASK_RUN_STATUS_RUNNING; + this.result = null; + this.data = null; + this.startedAt = new Date().toISOString(); + this.finishedAt = null; + this.duration = null; + this.error = null; + } + async run(...params) { + if (this.status === INITIALIZATION_TASK_RUN_STATUS_RUNNING) { + throw new Error(`Another instance of task ${this.name} is running`); + } + let error; + try { + this.init(); + this.data = await this._run(...params); + this.result = INITIALIZATION_TASK_RUN_RESULT_SUCCESS; + } catch (e) { + error = e; + this.result = INITIALIZATION_TASK_RUN_RESULT_FAIL; + this.error = e.message; + } finally { + this.status = INITIALIZATION_TASK_RUN_STATUS_FINISHED; + this.finishedAt = new Date().toISOString(); + const dateStartedAt = new Date(this.startedAt!); + const dateFinishedAt = new Date(this.finishedAt); + this.duration = ((dateFinishedAt - dateStartedAt) as number) / 1000; + } + if (error) { + throw error; + } + return this.getInfo(); + } + + getInfo() { + return [ + 'name', + 'status', + 'result', + 'data', + 'createdAt', + 'startedAt', + 'finishedAt', + 'duration', + 'error', + ].reduce( + (accum, item) => ({ + ...accum, + [item]: this[item], + }), + {}, + ) as IInitializationTask; + } +} diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index bbb51eb079..0f19549ad7 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -30,7 +30,7 @@ export type InitializationTaskContext = 'internal' | 'user'; export interface IInitializationService extends LifecycleService { register(task: InitializationTaskDefinition): void; - get(taskName?: string): InitializationTaskRunData; + get(taskName: string): InitializationTaskRunData; getAll(): InitializationTaskRunData[]; createRunContext( scope: InitializationTaskContext, From 5e03e8be5fbe2a11c81878b27a1ae3be65998804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 11:09:30 +0100 Subject: [PATCH 15/30] fix(initialization): add types --- .../server/initialization/server-api.ts | 9 +++++--- plugins/wazuh-core/server/services/index.ts | 1 + .../server/services/initialization/types.ts | 8 ++++++- plugins/wazuh-core/server/services/types.ts | 14 ++++++++++++ plugins/wazuh-core/server/types.ts | 22 +++++-------------- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index 843c4449c0..ab92208203 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -4,6 +4,7 @@ import { } from '../../common/constants'; import { webDocumentationLink } from '../../common/services/web_documentation'; import { version as appVersion } from '../../package.json'; +import { InitializationTaskRunContext } from '../services'; export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ taskName, @@ -11,7 +12,7 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ taskName: string; }) => ({ name: taskName, - async run(ctx) { + async run(ctx: InitializationTaskRunContext) { try { ctx.logger.debug( 'Starting check server API connection and compatibility', @@ -29,7 +30,9 @@ export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ }, }); -async function ServersAPIConnectionCompatibility(ctx) { +async function ServersAPIConnectionCompatibility( + ctx: InitializationTaskRunContext, +) { if (ctx.scope === 'user' && ctx.request?.query?.apiHostID) { const host = await ctx.manageHosts.get(ctx.request.query.apiHostID, { excludePassword: true, @@ -54,7 +57,7 @@ async function ServersAPIConnectionCompatibility(ctx) { } export async function ServerAPIConnectionCompatibility( - ctx: any, + ctx: InitializationTaskRunContext, apiHostID: string, appVersion: string, ) { diff --git a/plugins/wazuh-core/server/services/index.ts b/plugins/wazuh-core/server/services/index.ts index 9b064c7e99..1cf09c22bf 100644 --- a/plugins/wazuh-core/server/services/index.ts +++ b/plugins/wazuh-core/server/services/index.ts @@ -17,3 +17,4 @@ export * from './manage-hosts'; export * from './security-factory'; export * from './server-api-client'; export * from './initialization'; +export * from './types'; diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index 0f19549ad7..5992868232 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -2,7 +2,8 @@ import { InitializationTaskRunResult, InitializationTaskRunStatus, } from '../../../common/services/initialization/types'; -import { LifecycleService } from '../types'; +import { LifecycleService, WazuhCoreServices } from '../types'; +import { CoreStart, Logger } from '../../../../../core/server'; export interface InitializationTaskDefinition { name: string; @@ -40,3 +41,8 @@ export interface IInitializationService }; runAsInternal(tasks?: string[]): Promise; } + +export interface InitializationTaskRunContext extends WazuhCoreServices { + core: CoreStart; + logger: Logger; +} diff --git a/plugins/wazuh-core/server/services/types.ts b/plugins/wazuh-core/server/services/types.ts index 75147d110f..77a1c4fdf0 100644 --- a/plugins/wazuh-core/server/services/types.ts +++ b/plugins/wazuh-core/server/services/types.ts @@ -1,3 +1,9 @@ +import { IConfigurationEnhanced } from './enhance-configuration'; +import { IInitializationService } from './initialization'; +import { ManageHosts } from './manage-hosts'; +import { ISecurityFactory } from './security-factory'; +import { ServerAPIClient } from './server-api-client'; + export interface LifecycleService< SetupDeps = any, SetupReturn = any, @@ -10,3 +16,11 @@ export interface LifecycleService< start: (deps: StartDeps) => StartReturn; stop: (deps: StopDeps) => StopReturn; } + +export interface WazuhCoreServices { + dashboardSecurity: ISecurityFactory; + configuration: IConfigurationEnhanced; + manageHosts: ManageHosts; + serverAPIClient: ServerAPIClient; + initialization: IInitializationService; +} diff --git a/plugins/wazuh-core/server/types.ts b/plugins/wazuh-core/server/types.ts index f706b3ef28..998fd6f26a 100644 --- a/plugins/wazuh-core/server/types.ts +++ b/plugins/wazuh-core/server/types.ts @@ -1,20 +1,11 @@ import { - IInitializationService, - ISecurityFactory, - ManageHosts, - ServerAPIClient, ServerAPIInternalUserClient, ServerAPIScopedUserClient, + WazuhCoreServices, } from './services'; -import { IConfigurationEnhanced } from './services/enhance-configuration'; // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhCorePluginSetup { - dashboardSecurity: ISecurityFactory; - configuration: IConfigurationEnhanced; - manageHosts: ManageHosts; - serverAPIClient: ServerAPIClient; - initialization: IInitializationService; +export interface WazuhCorePluginSetup extends WazuhCoreServices { api: { client: { asInternalUser: ServerAPIInternalUserClient; @@ -23,12 +14,7 @@ export interface WazuhCorePluginSetup { }; } // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface WazuhCorePluginStart { - dashboardSecurity: ISecurityFactory; - configuration: IConfigurationEnhanced; - manageHosts: ManageHosts; - serverAPIClient: ServerAPIClient; - initialization: IInitializationService; +export interface WazuhCorePluginStart extends WazuhCoreServices { api: { client: { asInternalUser: ServerAPIInternalUserClient; @@ -40,3 +26,5 @@ export interface WazuhCorePluginStart { export type PluginSetup = { securityDashboards?: {}; // TODO: Add OpenSearch Dashboards Security interface }; + +export * from './services/initialization/types'; From d194092631743f3f77eb656f936949a689a42e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 13:56:35 +0100 Subject: [PATCH 16/30] fix(initialization): typo --- plugins/main/server/lib/initialization/index-patterns.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/main/server/lib/initialization/index-patterns.ts index 230cc71d5a..d19172a06f 100644 --- a/plugins/main/server/lib/initialization/index-patterns.ts +++ b/plugins/main/server/lib/initialization/index-patterns.ts @@ -5,7 +5,7 @@ interface ensureIndexPatternExistenceContextTask { options: any; } -interface ensureIndexPatternExistenceContextTaskWithCondifurationSetting +interface ensureIndexPatternExistenceContextTaskWithConfigurationSetting extends ensureIndexPatternExistenceContextTask { configurationSettingKey: string; } @@ -16,7 +16,7 @@ const decoratorCheckIsEnabled = fn => { { configurationSettingKey, ...ctxTask - }: ensureIndexPatternExistenceContextTaskWithCondifurationSetting, + }: ensureIndexPatternExistenceContextTaskWithConfigurationSetting, ) => { if (await ctx.configuration.get(configurationSettingKey)) { await fn(ctx, ctxTask); From fdc987cc19781bb2e46e4cb21135b8b719ff8f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 15:04:27 +0100 Subject: [PATCH 17/30] fix(initialization): move temporal registration to core plugin --- plugins/main/server/plugin.ts | 124 --- plugins/wazuh-core/server/index.ts | 2 +- .../monitoring-fields.json | 245 ++++++ .../statistics-fields.json | 710 ++++++++++++++++++ .../vulnerabibility-states-fields.json | 0 .../server}/initialization/index-patterns.ts | 2 +- .../server}/initialization/index.ts | 0 .../server}/initialization/settings.ts | 0 .../server}/initialization/templates.test.ts | 0 .../server}/initialization/templates.ts | 0 plugins/wazuh-core/server/plugin.ts | 121 +++ 11 files changed, 1078 insertions(+), 126 deletions(-) create mode 100644 plugins/wazuh-core/server/initialization/index-patterns-fields/monitoring-fields.json create mode 100644 plugins/wazuh-core/server/initialization/index-patterns-fields/statistics-fields.json rename plugins/{main/public/utils => wazuh-core/server/initialization/index-patterns-fields}/vulnerabibility-states-fields.json (100%) rename plugins/{main/server/lib => wazuh-core/server}/initialization/index-patterns.ts (98%) rename plugins/{main/server/lib => wazuh-core/server}/initialization/index.ts (100%) rename plugins/{main/server/lib => wazuh-core/server}/initialization/settings.ts (100%) rename plugins/{main/server/lib => wazuh-core/server}/initialization/templates.test.ts (100%) rename plugins/{main/server/lib => wazuh-core/server}/initialization/templates.ts (100%) diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index a52ece8d54..e37ec01792 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -37,23 +37,6 @@ import { jobSanitizeUploadedFilesTasksRun, } from './start'; import { first } from 'rxjs/operators'; -import { - initializationTaskCreatorIndexPattern, - initializationTaskCreatorSetting, - initializationTaskCreatorExistTemplate, -} from './lib/initialization'; -import { - PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, - PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, - PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, - WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, - WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, - WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER, -} from '../common/constants'; -import { KnownFields } from '../public/utils/known-fields'; -import { FieldsStatistics } from '../public/utils/statistics-fields'; -import { FieldsMonitoring } from '../public/utils/monitoring-fields'; -import VulnerabilitiesStatesFields from '../public/utils/vulnerabibility-states-fields.json'; declare module 'opensearch_dashboards/server' { interface RequestHandlerContext { @@ -126,113 +109,6 @@ export class WazuhPlugin implements Plugin { const router = core.http.createRouter(); setupRoutes(router, plugins.wazuhCore); - // Register initialization - // Index pattern: alerts - // TODO: this task should be registered by the related plugin - plugins.wazuhCore.initialization.register( - initializationTaskCreatorIndexPattern({ - getIndexPatternID: ctx => ctx.configuration.get('pattern'), - taskName: 'index-pattern:alerts', - options: { - savedObjectOverwrite: { - timeFieldName: 'timestamp', - }, - fieldsNoIndices: KnownFields, - }, - configurationSettingKey: 'checks.pattern', - }), - ); - // Index pattern: monitoring - // TODO: this task should be registered by the related plugin - plugins.wazuhCore.initialization.register( - initializationTaskCreatorIndexPattern({ - getIndexPatternID: ctx => - ctx.configuration.get('wazuh.monitoring.pattern'), - taskName: 'index-pattern:monitoring', - options: { - savedObjectOverwrite: { - timeFieldName: 'timestamp', - }, - fieldsNoIndices: FieldsMonitoring, - }, - configurationSettingKey: 'checks.monitoring', // TODO: create new setting - }), - ); - // Index pattern: vulnerabilities - // TODO: this task should be registered by the related plugin - plugins.wazuhCore.initialization.register( - initializationTaskCreatorIndexPattern({ - getIndexPatternID: ctx => - ctx.configuration.get('vulnerabilities.pattern'), - taskName: 'index-pattern:vulnerabilities-states', - options: { - fieldsNoIndices: VulnerabilitiesStatesFields, - }, - configurationSettingKey: 'checks.vulnerability', // TODO: create new setting - }), - ); - - // Index pattern: statistics - // TODO: this task should be registered by the related plugin - plugins.wazuhCore.initialization.register( - initializationTaskCreatorIndexPattern({ - getIndexPatternID: async ctx => { - const appConfig = await ctx.configuration.get( - 'cron.prefix', - 'cron.statistics.index.name', - ); - - const prefixTemplateName = appConfig['cron.prefix']; - const statisticsIndicesTemplateName = - appConfig['cron.statistics.index.name']; - return `${prefixTemplateName}-${statisticsIndicesTemplateName}-*`; - }, - taskName: 'index-pattern:statistics', - options: { - savedObjectOverwrite: { - timeFieldName: 'timestamp', - }, - fieldsNoIndices: FieldsStatistics, - }, - configurationSettingKey: 'checks.statistics', // TODO: create new setting - }), - ); - - // Settings - // TODO: this task should be registered by the related plugin - [ - { - key: PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, - value: WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, - configurationSetting: 'checks.maxBuckets', - }, - { - key: PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, - value: WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, - configurationSetting: 'checks.metaFields', - }, - { - key: PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, - value: JSON.stringify(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER), - configurationSetting: 'checks.timeFilter', - }, - ].forEach(setting => { - plugins.wazuhCore.initialization.register( - initializationTaskCreatorSetting(setting, `setting:${setting.key}`), - ); - }); - - // Index pattern templates - // Index pattern template: alerts - // TODO: this task should be registered by the related plugin - plugins.wazuhCore.initialization.register( - initializationTaskCreatorExistTemplate({ - getOpenSearchClient: ctx => ctx.core.opensearch.client.asInternalUser, - getIndexPatternTitle: ctx => ctx.configuration.get('pattern'), - taskName: 'index-pattern-template:alerts', - }), - ); - return {}; } diff --git a/plugins/wazuh-core/server/index.ts b/plugins/wazuh-core/server/index.ts index adf9ef623d..26e39fdf47 100644 --- a/plugins/wazuh-core/server/index.ts +++ b/plugins/wazuh-core/server/index.ts @@ -8,5 +8,5 @@ export function plugin(initializerContext: PluginInitializerContext) { return new WazuhCorePlugin(initializerContext); } -export type { WazuhCorePluginSetup, WazuhCorePluginStart } from './types'; +export * from './types'; export type { IConfigurationEnhanced } from './services/enhance-configuration'; diff --git a/plugins/wazuh-core/server/initialization/index-patterns-fields/monitoring-fields.json b/plugins/wazuh-core/server/initialization/index-patterns-fields/monitoring-fields.json new file mode 100644 index 0000000000..6b82becbdf --- /dev/null +++ b/plugins/wazuh-core/server/initialization/index-patterns-fields/monitoring-fields.json @@ -0,0 +1,245 @@ +[ + { + "name": "timestamp", + "type": "date", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "_id", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_index", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_score", + "type": "number", + "count": 0, + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_source", + "type": "_source", + "count": 0, + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_type", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "dateAdd", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "group", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "host", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "id", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "ip", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "lastKeepAlive", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "cluster.name", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "mergedSum", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "configSum", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "node_name", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "manager", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "name", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "os.arch", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.codename", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.major", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.name", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.platform", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.uname", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "os.version", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "status", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "version", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + } +] diff --git a/plugins/wazuh-core/server/initialization/index-patterns-fields/statistics-fields.json b/plugins/wazuh-core/server/initialization/index-patterns-fields/statistics-fields.json new file mode 100644 index 0000000000..c89d99d72f --- /dev/null +++ b/plugins/wazuh-core/server/initialization/index-patterns-fields/statistics-fields.json @@ -0,0 +1,710 @@ +[ + { + "name": "analysisd.alerts_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.alerts_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.alerts_written", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.archives_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.archives_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.dbsync_mdps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.dbsync_messages_dispatched", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.dbsync_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.dbsync_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.event_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.event_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.events_dropped", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.events_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.events_processed", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.events_received", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.firewall_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.firewall_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.firewall_written", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.fts_written", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.hostinfo_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.hostinfo_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.hostinfo_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.hostinfo_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.other_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.other_events_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rootcheck_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rootcheck_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rootcheck_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rootcheck_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rule_matching_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.rule_matching_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.sca_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.sca_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.sca_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.sca_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.statistical_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.statistical_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscheck_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscheck_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscheck_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscheck_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscollector_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscollector_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscollector_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.syscollector_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.total_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.winevt_edps", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.winevt_events_decoded", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.winevt_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "analysisd.winevt_queue_usage", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "apiName", + "type": "string", + "esTypes": ["text"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "apiName.keyword", + "type": "string", + "esTypes": ["keyword"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true, + "subType": { "multi": { "parent": "apiName" } } + }, + { + "name": "cluster", + "type": "string", + "esTypes": ["text"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "cluster.keyword", + "type": "string", + "esTypes": ["keyword"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true, + "subType": { "multi": { "parent": "cluster" } } + }, + { + "name": "nodeName", + "type": "string", + "esTypes": ["text"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "nodeName.keyword", + "type": "string", + "esTypes": ["keyword"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true, + "subType": { "multi": { "parent": "nodeName" } } + }, + { + "name": "remoted.ctrl_msg_count", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.dequeued_after_close", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.discarded_count", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.evt_count", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.msg_sent", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.recv_bytes", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.tcp_sessions", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "remoted.total_queue_size", + "type": "number", + "esTypes": ["long"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "timestamp", + "type": "date", + "esTypes": ["date"], + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "_id", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_index", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_score", + "type": "number", + "count": 0, + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_source", + "type": "_source", + "count": 0, + "scripted": false, + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_type", + "type": "string", + "count": 0, + "scripted": false, + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + } +] diff --git a/plugins/main/public/utils/vulnerabibility-states-fields.json b/plugins/wazuh-core/server/initialization/index-patterns-fields/vulnerabibility-states-fields.json similarity index 100% rename from plugins/main/public/utils/vulnerabibility-states-fields.json rename to plugins/wazuh-core/server/initialization/index-patterns-fields/vulnerabibility-states-fields.json diff --git a/plugins/main/server/lib/initialization/index-patterns.ts b/plugins/wazuh-core/server/initialization/index-patterns.ts similarity index 98% rename from plugins/main/server/lib/initialization/index-patterns.ts rename to plugins/wazuh-core/server/initialization/index-patterns.ts index d19172a06f..e72ebffcaf 100644 --- a/plugins/main/server/lib/initialization/index-patterns.ts +++ b/plugins/wazuh-core/server/initialization/index-patterns.ts @@ -1,4 +1,4 @@ -import { IndexPatternsFetcher } from '../../../../../src/plugins/data/server'; +import { IndexPatternsFetcher } from '../../../../src/plugins/data/server'; interface ensureIndexPatternExistenceContextTask { indexPatternID: string; diff --git a/plugins/main/server/lib/initialization/index.ts b/plugins/wazuh-core/server/initialization/index.ts similarity index 100% rename from plugins/main/server/lib/initialization/index.ts rename to plugins/wazuh-core/server/initialization/index.ts diff --git a/plugins/main/server/lib/initialization/settings.ts b/plugins/wazuh-core/server/initialization/settings.ts similarity index 100% rename from plugins/main/server/lib/initialization/settings.ts rename to plugins/wazuh-core/server/initialization/settings.ts diff --git a/plugins/main/server/lib/initialization/templates.test.ts b/plugins/wazuh-core/server/initialization/templates.test.ts similarity index 100% rename from plugins/main/server/lib/initialization/templates.test.ts rename to plugins/wazuh-core/server/initialization/templates.test.ts diff --git a/plugins/main/server/lib/initialization/templates.ts b/plugins/wazuh-core/server/initialization/templates.ts similarity index 100% rename from plugins/main/server/lib/initialization/templates.ts rename to plugins/wazuh-core/server/initialization/templates.ts diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index 3cad414216..afb08f0f1a 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -21,13 +21,28 @@ import { } from './services'; import { Configuration } from '../common/services/configuration'; import { + PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, + PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, + PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, PLUGIN_SETTINGS, PLUGIN_SETTINGS_CATEGORIES, WAZUH_CORE_CONFIGURATION_CACHE_SECONDS, WAZUH_DATA_CONFIG_APP_PATH, + WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, + WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, + WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER, } from '../common/constants'; import { enhanceConfiguration } from './services/enhance-configuration'; import { initializationTaskCreatorServerAPIConnectionCompatibility } from './initialization/server-api'; +import { + initializationTaskCreatorExistTemplate, + initializationTaskCreatorIndexPattern, + initializationTaskCreatorSetting, +} from './initialization'; +import AlertsIndexPatternDefaultFields from './initialization/index-patterns-fields/alerts-fields.json'; +import MonitoringIndexPatternDefaultFields from './initialization/index-patterns-fields/monitoring-fields.json'; +import StatisticsIndexPatternDefaultFields from './initialization/index-patterns-fields/statistics-fields.json'; +import VulnerabilitiesStatesFields from './initialization/index-patterns-fields/vulnerabibility-states-fields.json'; export class WazuhCorePlugin implements Plugin @@ -122,6 +137,112 @@ export class WazuhCorePlugin }), ); + // Index pattern: alerts + // TODO: this task should be registered by the related plugin + this.services.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => ctx.configuration.get('pattern'), + taskName: 'index-pattern:alerts', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: AlertsIndexPatternDefaultFields, + }, + configurationSettingKey: 'checks.pattern', + }), + ); + // Index pattern: monitoring + // TODO: this task should be registered by the related plugin + this.services.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => + ctx.configuration.get('wazuh.monitoring.pattern'), + taskName: 'index-pattern:monitoring', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: MonitoringIndexPatternDefaultFields, + }, + configurationSettingKey: 'checks.monitoring', // TODO: create new setting + }), + ); + // Index pattern: vulnerabilities + // TODO: this task should be registered by the related plugin + this.services.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: ctx => + ctx.configuration.get('vulnerabilities.pattern'), + taskName: 'index-pattern:vulnerabilities-states', + options: { + fieldsNoIndices: VulnerabilitiesStatesFields, + }, + configurationSettingKey: 'checks.vulnerability', // TODO: create new setting + }), + ); + + // Index pattern: statistics + // TODO: this task should be registered by the related plugin + this.services.initialization.register( + initializationTaskCreatorIndexPattern({ + getIndexPatternID: async ctx => { + const appConfig = await ctx.configuration.get( + 'cron.prefix', + 'cron.statistics.index.name', + ); + + const prefixTemplateName = appConfig['cron.prefix']; + const statisticsIndicesTemplateName = + appConfig['cron.statistics.index.name']; + return `${prefixTemplateName}-${statisticsIndicesTemplateName}-*`; + }, + taskName: 'index-pattern:statistics', + options: { + savedObjectOverwrite: { + timeFieldName: 'timestamp', + }, + fieldsNoIndices: StatisticsIndexPatternDefaultFields, + }, + configurationSettingKey: 'checks.statistics', // TODO: create new setting + }), + ); + + // Settings + // TODO: this task should be registered by the related plugin + [ + { + key: PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, + value: WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, + configurationSetting: 'checks.maxBuckets', + }, + { + key: PLUGIN_PLATFORM_SETTING_NAME_METAFIELDS, + value: WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, + configurationSetting: 'checks.metaFields', + }, + { + key: PLUGIN_PLATFORM_SETTING_NAME_TIME_FILTER, + value: JSON.stringify(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER), + configurationSetting: 'checks.timeFilter', + }, + ].forEach(setting => { + this.services.initialization.register( + initializationTaskCreatorSetting(setting, `setting:${setting.key}`), + ); + }); + + // Index pattern templates + // Index pattern template: alerts + // TODO: this task should be registered by the related plugin + this.services.initialization.register( + initializationTaskCreatorExistTemplate({ + getOpenSearchClient: ctx => ctx.core.opensearch.client.asInternalUser, + getIndexPatternTitle: ctx => ctx.configuration.get('pattern'), + taskName: 'index-pattern-template:alerts', + }), + ); + // Register a property to the context parameter of the endpoint handlers core.http.registerRouteHandlerContext('wazuh_core', (context, request) => { return { From e3b1cc4bc1a254a9c757dfaeef27f633417fb512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 15:05:55 +0100 Subject: [PATCH 18/30] fix(initialization): add missing default index pattern fields for alerts --- .../index-patterns-fields/alerts-fields.json | 3473 +++++++++++++++++ 1 file changed, 3473 insertions(+) create mode 100644 plugins/wazuh-core/server/initialization/index-patterns-fields/alerts-fields.json diff --git a/plugins/wazuh-core/server/initialization/index-patterns-fields/alerts-fields.json b/plugins/wazuh-core/server/initialization/index-patterns-fields/alerts-fields.json new file mode 100644 index 0000000000..56048c13d6 --- /dev/null +++ b/plugins/wazuh-core/server/initialization/index-patterns-fields/alerts-fields.json @@ -0,0 +1,3473 @@ +[ + { + "name": "_id", + "type": "string", + "esTypes": ["_id"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_index", + "type": "string", + "esTypes": ["_index"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "_score", + "type": "number", + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_source", + "type": "_source", + "esTypes": ["_source"], + "searchable": false, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "_type", + "type": "string", + "esTypes": ["_type"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": false + }, + { + "name": "@timestamp", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "@version", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "GeoLocation.area_code", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.city_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.continent_code", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "GeoLocation.coordinates", + "type": "number", + "esTypes": ["double"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.country_code2", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "GeoLocation.country_code3", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "GeoLocation.country_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.dma_code", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.ip", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.latitude", + "type": "number", + "esTypes": ["double"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.location", + "type": "geo_point", + "esTypes": ["geo_point"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.longitude", + "type": "number", + "esTypes": ["double"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.postal_code", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.real_region_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.region_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "GeoLocation.timezone", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "agent.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "agent.ip", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "agent.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "cluster.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "cluster.node", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "command", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.action", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.acct", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.arch", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.auid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.command", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.cwd", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.dev", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.directory.inode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.directory.mode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.directory.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.egid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.enforcing", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.euid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.exe", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.execve.a0", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.execve.a1", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.execve.a2", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.execve.a3", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.exit", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.file.inode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.file.mode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.file.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.fsgid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.fsuid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.gid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.key", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.list", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.old-auid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.old-ses", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.old_enforcing", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.old_prom", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.op", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.pid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.ppid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.prom", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.res", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.session", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.sgid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.srcip", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.subj", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.success", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.suid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.syscall", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.tty", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.audit.uid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.bytes", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.createdAt", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.dstaddr", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.end", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.resource.instanceDetails.launchTime", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.resource.instanceDetails.networkInterfaces.privateIpAddress", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.resource.instanceDetails.networkInterfaces.publicIp", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.service.action.networkConnectionAction.remoteIpDetails.geoLocation", + "type": "geo_point", + "esTypes": ["geo_point"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.service.action.networkConnectionAction.remoteIpDetails.ipAddressV4", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.service.count", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.service.eventFirstSeen", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.service.eventLastSeen", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.source_ip_address", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.srcaddr", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.start", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.updatedAt", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.log_info.s3bucket", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.source", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.accountId", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.aws.region", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.benchmark", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.error", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.fail", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.group", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.notchecked", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.pass", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.result", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.rule_title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.score", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.timestamp", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.cis.unknown", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.command", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.data", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.docker.Action", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.docker.Actor.Attributes.image", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.docker.Actor.Attributes.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.docker.Type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.dstip", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.dstport", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.dstuser", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.extra_data", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.file", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.jsonPayload.authAnswer", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.jsonPayload.queryName", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.jsonPayload.responseCode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.jsonPayload.vmInstanceId", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.jsonPayload.vmInstanceName", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.resource.labels.location", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.resource.labels.project_id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.resource.labels.source_type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.resource.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.gcp.severity", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.github.action", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.github.actor", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.github.actor_location.country_code", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.github.org", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.github.repo", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.cpu_cores", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.cpu_mhz", + "type": "number", + "esTypes": ["double"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.cpu_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.ram_free", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.ram_total", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.ram_usage", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.hardware.serial", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.integration", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.adapter", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.address", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.broadcast", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.dhcp", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.gateway", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.metric", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv4.netmask", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.address", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.broadcast", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.dhcp", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.gateway", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.metric", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.ipv6.netmask", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.mac", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.mtu", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.rx_bytes", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.rx_dropped", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.rx_errors", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.rx_packets", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.state", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.tx_bytes", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.tx_dropped", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.tx_errors", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.tx_packets", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.netinfo.iface.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.Actor.ID", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.ClientIP", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.Operation", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.ResultStatus", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.Subscription", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.office365.UserId", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.architecture", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.build", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.codename", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.hostname", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.major", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.minor", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.platform", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.release", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.release_version", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.sysname", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.os.version", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.check.description", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "data.oscap.check.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.check.identifiers", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "data.oscap.check.oval.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.check.rationale", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "data.oscap.check.references", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "data.oscap.check.result", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.check.severity", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.check.title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.benchmark.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.content", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.profile.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.profile.title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.return_code", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.oscap.scan.score", + "type": "number", + "esTypes": ["double"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.osquery.action", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.osquery.calendarTime", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.osquery.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.osquery.pack", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.inode", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.local_ip", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.local_port", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.pid", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.process", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.protocol", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.remote_ip", + "type": "ip", + "esTypes": ["ip"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.remote_port", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.rx_queue", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.state", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.port.tx_queue", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.args", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.cmd", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.egroup", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.euser", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.fgroup", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.nice", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.nlwp", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.pgrp", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.pid", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.ppid", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.priority", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.processor", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.resident", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.rgroup", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.ruser", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.session", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.sgroup", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.share", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.size", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.start_time", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.state", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.stime", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.suser", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.tgid", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.tty", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.utime", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.process.vm_size", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.architecture", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.description", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.format", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.install_time", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.location", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.multiarch", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.priority", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.section", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.size", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.source", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.vendor", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.program.version", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.protocol", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.command", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.compliance.cis", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.compliance.cis_csc", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.compliance.hipaa", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.compliance.nist_800_53", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.compliance.pci_dss", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.description", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.directory", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.file", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.previous_result", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.process", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.rationale", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.reason", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.references", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.registry", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.remediation", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.result", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.status", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.check.title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.description", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.failed", + "type": "number", + "esTypes": ["integer"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.file", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.invalid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.passed", + "type": "number", + "esTypes": ["integer"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.policy", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.policy_id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.scan_id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.score", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.total_checks", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.sca.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.srcip", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.srcport", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.srcuser", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.status", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.system_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.timestamp", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.uid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.url", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.description", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.error", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.found", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.malicious", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.permalink", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.positives", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.scan_date", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.sha1", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.source.alert_id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.source.file", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.source.md5", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.source.sha1", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.virustotal.total", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.assigner", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cve", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cve_version", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.base_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.exploitability_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.impact_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.access_complexity", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.attack_vector", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.authentication", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.availability", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.confidentiality_impact", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.integrity_impact", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.privileges_required", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.scope", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss2.vector.user_interaction", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.base_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.exploitability_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.impact_score", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.access_complexity", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.attack_vector", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.authentication", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.availability", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.confidentiality_impact", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.integrity_impact", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.privileges_required", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.scope", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cvss.cvss3.vector.user_interaction", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.cwe_reference", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.architecture", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.condition", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.generated_cpe", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.source", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.package.version", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.published", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.rationale", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.severity", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "data.vulnerability.updated", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "decoder.accumulate", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "decoder.fts", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "decoder.ftscomment", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "decoder.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "decoder.parent", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "full_log", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "host", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "input.type", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "location", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "manager.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "message", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "offset", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "predecoder.hostname", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "predecoder.program_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "predecoder.timestamp", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "previous_log", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + }, + { + "name": "previous_output", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "program_name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.cis", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.cis_csc", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.cve", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.description", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.firedtimes", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.frequency", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.gdpr", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.gpg13", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.groups", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.hipaa", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.info", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.level", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.mail", + "type": "boolean", + "esTypes": ["boolean"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.mitre.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.mitre.tactic", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.mitre.technique", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.nist_800_53", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.pci_dss", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "rule.tsc", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.effective_user.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.effective_user.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.group.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.group.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.login_user.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.login_user.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.process.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.process.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.process.ppid", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.user.id", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.audit.user.name", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.diff", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.event", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.gid_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.gid_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.gname_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.gname_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.hard_links", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.inode_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.inode_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.md5_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.md5_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.mode", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.mtime_after", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.mtime_before", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.path", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.perm_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.perm_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.sha1_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.sha1_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.sha256_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.sha256_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.size_after", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.size_before", + "type": "number", + "esTypes": ["long"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.tags", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.uid_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.uid_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.uname_after", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "syscheck.uname_before", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "timestamp", + "type": "date", + "esTypes": ["date"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "title", + "type": "string", + "esTypes": ["keyword"], + "searchable": true, + "aggregatable": true, + "readFromDocValues": true + }, + { + "name": "type", + "type": "string", + "esTypes": ["text"], + "searchable": true, + "aggregatable": false, + "readFromDocValues": false + } +] From 90c99aa6c6cb1aed064e007a6a77f65b278fce6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 15:18:59 +0100 Subject: [PATCH 19/30] fix(initialization): enhance types and rename error variable --- .../server/initialization/index-patterns.ts | 38 +++++++++++++------ .../server/initialization/settings.ts | 23 ++++++++--- .../server/initialization/templates.ts | 19 ++++++---- .../services/initialization/initialization.ts | 6 ++- .../server/services/initialization/types.ts | 1 + 5 files changed, 60 insertions(+), 27 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/index-patterns.ts b/plugins/wazuh-core/server/initialization/index-patterns.ts index e72ebffcaf..012f8be2a8 100644 --- a/plugins/wazuh-core/server/initialization/index-patterns.ts +++ b/plugins/wazuh-core/server/initialization/index-patterns.ts @@ -1,4 +1,8 @@ import { IndexPatternsFetcher } from '../../../../src/plugins/data/server'; +import { + InitializationTaskContext, + InitializationTaskRunContext, +} from '../services'; interface ensureIndexPatternExistenceContextTask { indexPatternID: string; @@ -12,7 +16,7 @@ interface ensureIndexPatternExistenceContextTaskWithConfigurationSetting const decoratorCheckIsEnabled = fn => { return async ( - ctx, + ctx: InitializationTaskRunContext, { configurationSettingKey, ...ctxTask @@ -40,9 +44,9 @@ export const ensureIndexPatternExistence = async ( ); logger.debug(`Index pattern with ID [${indexPatternID}] exists`); return response; - } catch (e) { + } catch (error) { // Get not found saved object - if (e?.output?.statusCode === 404) { + if (error?.output?.statusCode === 404) { // Create index pattern logger.info(`Index pattern with ID [${indexPatternID}] does not exist`); return await createIndexPattern( @@ -52,7 +56,7 @@ export const ensureIndexPatternExistence = async ( ); } else { throw new Error( - `index pattern with ID [${indexPatternID}] existence could not be checked due to: ${e.message}`, + `index pattern with ID [${indexPatternID}] existence could not be checked due to: ${error.message}`, ); } } @@ -126,14 +130,17 @@ async function createIndexPattern( const indexPatternCreatedMessage = `Created index pattern with ID [${response.id}] title [${response.attributes.title}]`; logger.info(indexPatternCreatedMessage); return response; - } catch (e) { + } catch (error) { throw new Error( - `index pattern with ID [${indexPatternID}] could not be created due to: ${e.message}`, + `index pattern with ID [${indexPatternID}] could not be created due to: ${error.message}`, ); } } -function getSavedObjectsClient(ctx: any, scope) { +function getSavedObjectsClient( + ctx: InitializationTaskRunContext, + scope: InitializationTaskContext, +) { switch (scope) { case 'internal': return ctx.core.savedObjects.createInternalRepository(); @@ -148,7 +155,10 @@ function getSavedObjectsClient(ctx: any, scope) { } } -function getIndexPatternsClient(ctx: any, scope) { +function getIndexPatternsClient( + ctx: InitializationTaskRunContext, + scope: InitializationTaskContext, +) { switch (scope) { case 'internal': return new IndexPatternsFetcher( @@ -165,7 +175,11 @@ function getIndexPatternsClient(ctx: any, scope) { } } -function getIndexPatternID(ctx: any, scope: string, rest: any) { +function getIndexPatternID( + ctx: InitializationTaskRunContext, + scope: string, + rest: any, +) { switch (scope) { case 'internal': return rest.getIndexPatternID(ctx); @@ -190,7 +204,7 @@ export const initializationTaskCreatorIndexPattern = ({ configurationSettingKey: string; }) => ({ name: taskName, - async run(ctx) { + async run(ctx: InitializationTaskRunContext) { let indexPatternID; try { ctx.logger.debug('Starting index pattern saved object'); @@ -208,8 +222,8 @@ export const initializationTaskCreatorIndexPattern = ({ configurationSettingKey, }, ); - } catch (e) { - const message = `Error initilizating index pattern with ID [${indexPatternID}]: ${e.message}`; + } catch (error) { + const message = `Error initilizating index pattern with ID [${indexPatternID}]: ${error.message}`; ctx.logger.error(message); throw new Error(message); } diff --git a/plugins/wazuh-core/server/initialization/settings.ts b/plugins/wazuh-core/server/initialization/settings.ts index 3ee6ff3990..5d861508a2 100644 --- a/plugins/wazuh-core/server/initialization/settings.ts +++ b/plugins/wazuh-core/server/initialization/settings.ts @@ -13,10 +13,14 @@ */ import { isEqual } from 'lodash'; +import { + InitializationTaskContext, + InitializationTaskRunContext, +} from '../services'; const decoratorCheckIsEnabled = fn => { return async ( - ctx, + ctx: InitializationTaskRunContext, { configurationSetting, ...ctxTask @@ -111,7 +115,10 @@ function stringifySetting(setting: any) { } } -function getSavedObjectsClient(ctx: any, scope) { +function getSavedObjectsClient( + ctx: InitializationTaskRunContext, + scope: InitializationTaskContext, +) { switch (scope) { case 'internal': return ctx.core.savedObjects.createInternalRepository(); @@ -124,7 +131,11 @@ function getSavedObjectsClient(ctx: any, scope) { } } -function getUiSettingsClient(ctx, scope, client) { +function getUiSettingsClient( + ctx: InitializationTaskRunContext, + scope: InitializationTaskContext, + client, +) { switch (scope) { case 'internal': return ctx.core.uiSettings.asScopedToClient(client); @@ -142,7 +153,7 @@ export const initializationTaskCreatorSetting = ( taskName: string, ) => ({ name: taskName, - async run(ctx) { + async run(ctx: InitializationTaskRunContext) { try { ctx.logger.debug('Starting setting'); @@ -169,8 +180,8 @@ export const initializationTaskCreatorSetting = ( }, ); ctx.logger.info('Start setting finished'); - } catch (e) { - const message = `Error initilizating setting [${setting.key}]: ${e.message}`; + } catch (error) { + const message = `Error initilizating setting [${setting.key}]: ${error.message}`; ctx.logger.error(message); throw new Error(message); } diff --git a/plugins/wazuh-core/server/initialization/templates.ts b/plugins/wazuh-core/server/initialization/templates.ts index 4315c186d3..085cfb8d2c 100644 --- a/plugins/wazuh-core/server/initialization/templates.ts +++ b/plugins/wazuh-core/server/initialization/templates.ts @@ -1,6 +1,11 @@ +import { InitializationTaskRunContext } from '../services'; + export const checkIndexPatternHasTemplate = async ( - { logger }, - { indexPatternTitle, opensearchClient }, + { logger }: InitializationTaskRunContext, + { + indexPatternTitle, + opensearchClient, + }: { indexPatternTitle: string; opensearchClient: any }, ) => { logger.debug('Getting templates'); const data = await opensearchClient.cat.templates({ format: 'json' }); @@ -65,12 +70,12 @@ export const initializationTaskCreatorExistTemplate = ({ getIndexPatternTitle, taskName, }: { - getOpenSearchClient: (ctx: any) => any; - getIndexPatternTitle: (ctx: any) => Promise; + getOpenSearchClient: (ctx: InitializationTaskRunContext) => any; + getIndexPatternTitle: (ctx: InitializationTaskRunContext) => Promise; taskName: string; }) => ({ name: taskName, - async run(ctx) { + async run(ctx: InitializationTaskRunContext) { let indexPatternTitle; try { ctx.logger.debug('Starting check of existent template'); @@ -82,8 +87,8 @@ export const initializationTaskCreatorExistTemplate = ({ indexPatternTitle, }); ctx.logger.info('Start check of existent template finished'); - } catch (e) { - const message = `Error checking of existent template for index pattern with title [${indexPatternTitle}]: ${e.message}`; + } catch (error) { + const message = `Error checking of existent template for index pattern with title [${indexPatternTitle}]: ${error.message}`; ctx.logger.error(message); throw new Error(message); } diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index 95cbe18ba0..f47ae76c97 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -88,8 +88,10 @@ export class InitializationService implements IInitializationService { ...ctx, logger, }); - } catch (e) { - logger.error(`Error running task [${item.name}]: ${e.message}`); + } catch (error) { + logger.error( + `Error running task [${item.name}]: ${error.message}`, + ); return item.getInfo(); } }), diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index 5992868232..00eea6bb2b 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -45,4 +45,5 @@ export interface IInitializationService export interface InitializationTaskRunContext extends WazuhCoreServices { core: CoreStart; logger: Logger; + scope: InitializationTaskContext; } From 83ea8560e9e8937c4c96cf03bc2904993bb5ee21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 15:22:17 +0100 Subject: [PATCH 20/30] fix(initialization): variable name in test --- plugins/wazuh-core/server/initialization/server-api.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index c0d4ffa4d7..d9d03c865a 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -11,7 +11,7 @@ import { describe('checkAppServerCompatibility', () => { it.each` - appVersion | serverAPIVersion | result + appVersion | serverAPIVersion | isCompatible ${'5.0.0'} | ${'5.0.0'} | ${true} ${'5.0.0'} | ${'5.0.1'} | ${true} ${'5.0.0'} | ${'5.0.10'} | ${true} @@ -26,8 +26,8 @@ describe('checkAppServerCompatibility', () => { ${'5.0.0'} | ${'4.10.10'} | ${false} ${'5.0.0'} | ${'4.10.100'} | ${false} `( - `appVersion: $appVersion, serverAPIVersion: $serverAPIVersion, result: $result`, - ({ appVersion, serverAPIVersion, result }) => { + `appVersion: $appVersion, serverAPIVersion: $serverAPIVersion, isCompatible: $isCompatible`, + ({ appVersion, serverAPIVersion, isCompatible }) => { expect(checkAppServerCompatibility(appVersion, serverAPIVersion)).toBe( result, ); From 92f6d0c822143f80cbd53fc30d05f0335f803381 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 15:22:55 +0100 Subject: [PATCH 21/30] fix(initialization): enhance types and rename error variable --- plugins/wazuh-core/server/initialization/server-api.test.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index d9d03c865a..dfe1e20c13 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -29,7 +29,7 @@ describe('checkAppServerCompatibility', () => { `appVersion: $appVersion, serverAPIVersion: $serverAPIVersion, isCompatible: $isCompatible`, ({ appVersion, serverAPIVersion, isCompatible }) => { expect(checkAppServerCompatibility(appVersion, serverAPIVersion)).toBe( - result, + isCompatible, ); }, ); From fa3b79a2ca6a9881387a8d96ffd0f6a8d1990501 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 17:28:42 +0100 Subject: [PATCH 22/30] fix(initialization): enhance types --- .../wazuh-core/server/initialization/settings.ts | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/settings.ts b/plugins/wazuh-core/server/initialization/settings.ts index 5d861508a2..59d5c01644 100644 --- a/plugins/wazuh-core/server/initialization/settings.ts +++ b/plugins/wazuh-core/server/initialization/settings.ts @@ -17,6 +17,7 @@ import { InitializationTaskContext, InitializationTaskRunContext, } from '../services'; +import { IUiSettingsClient } from 'src/core/server'; const decoratorCheckIsEnabled = fn => { return async ( @@ -36,7 +37,7 @@ const decoratorCheckIsEnabled = fn => { export const checkPluginPlatformSettings = decoratorCheckIsEnabled( async ( - { logger, uiSettingsClient }, + { logger, uiSettingsClient }: InitializationTaskRunContext & {uiSettingsClient: IUiSettingsClient}, { key: pluginPlatformSettingName, value: defaultAppValue, @@ -87,11 +88,11 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( ); async function updateSetting( - uiSettingsClient, - pluginPlatformSettingName, - defaultAppValue, - retries = 3, -) { + uiSettingsClient: IUiSettingsClient, + pluginPlatformSettingName: string, + defaultAppValue: any, + retries: number = 3, +): Promise { return await uiSettingsClient .set(pluginPlatformSettingName, defaultAppValue) .catch(async error => { @@ -134,7 +135,7 @@ function getSavedObjectsClient( function getUiSettingsClient( ctx: InitializationTaskRunContext, scope: InitializationTaskContext, - client, + client: any, ) { switch (scope) { case 'internal': From 0fbe92ae88cba6d4698107535c6089b6a00a59e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Tue, 26 Nov 2024 17:40:49 +0100 Subject: [PATCH 23/30] fix(prettier): initalization task --- plugins/wazuh-core/server/initialization/settings.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/plugins/wazuh-core/server/initialization/settings.ts b/plugins/wazuh-core/server/initialization/settings.ts index 59d5c01644..4c92d31663 100644 --- a/plugins/wazuh-core/server/initialization/settings.ts +++ b/plugins/wazuh-core/server/initialization/settings.ts @@ -37,7 +37,10 @@ const decoratorCheckIsEnabled = fn => { export const checkPluginPlatformSettings = decoratorCheckIsEnabled( async ( - { logger, uiSettingsClient }: InitializationTaskRunContext & {uiSettingsClient: IUiSettingsClient}, + { + logger, + uiSettingsClient, + }: InitializationTaskRunContext & { uiSettingsClient: IUiSettingsClient }, { key: pluginPlatformSettingName, value: defaultAppValue, From bff0b538cc3a9dd9c18d6e63e933bef010dd1ef9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Wed, 27 Nov 2024 10:17:14 +0100 Subject: [PATCH 24/30] chore(changelog): add entry --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6eb7cf1177..ace26016b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Support for Wazuh 5.0.0 - Added creation of report definition when creating dashboard by reference and the button to reset the report [#7091](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7091) +- Added an initilization service to core plugin to run the initilization tasks related to user scope [#7145](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7145) ### Removed From c01b2aa4bde0109bb24893e866564ee9552e2f45 Mon Sep 17 00:00:00 2001 From: Antonio <34042064+Desvelao@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:44:38 +0100 Subject: [PATCH 25/30] Update plugins/wazuh-core/common/services/initialization/constants.ts Co-authored-by: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> --- .../services/initialization/constants.ts | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/plugins/wazuh-core/common/services/initialization/constants.ts b/plugins/wazuh-core/common/services/initialization/constants.ts index 90a9c27228..42f427a5ea 100644 --- a/plugins/wazuh-core/common/services/initialization/constants.ts +++ b/plugins/wazuh-core/common/services/initialization/constants.ts @@ -1,9 +1,16 @@ -export const INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED = 'not_started'; -export const INITIALIZATION_TASK_RUN_STATUS_RUNNING = 'running'; -export const INITIALIZATION_TASK_RUN_STATUS_FINISHED = 'finished'; -export const INITIALIZATION_TASK_RUN_RESULT_NULL = null; -export const INITIALIZATION_TASK_RUN_RESULT_SUCCESS = 'success'; -export const INITIALIZATION_TASK_RUN_RESULT_FAIL = 'fail'; - -export const INITIALIZATION_TASK_CONTEXT_INTERNAL = 'internal'; -export const INITIALIZATION_TASK_CONTEXT_USER = 'user'; +export const INITIALIZATION_TASK = { + RUN_STATUS: { + NOT_STARTED: 'not_started', + RUNNING: 'running', + FINISHED: 'finished', + }, + RUN_RESULT: { + NULL: null, + SUCCESS: 'success', + FAIL: 'fail', + }, + CONTEXT: { + INTERNAL: 'internal', + USER: 'user', + }, +} as const; From 1df7f7a38907a2647a7ce723263a6b2e52e4d06b Mon Sep 17 00:00:00 2001 From: Antonio <34042064+Desvelao@users.noreply.github.com> Date: Thu, 28 Nov 2024 16:44:53 +0100 Subject: [PATCH 26/30] Update plugins/wazuh-core/common/services/initialization/types.ts Co-authored-by: Guido Modarelli <38738725+guidomodarelli@users.noreply.github.com> --- .../common/services/initialization/types.ts | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/plugins/wazuh-core/common/services/initialization/types.ts b/plugins/wazuh-core/common/services/initialization/types.ts index 2b4e2d164d..93894a003e 100644 --- a/plugins/wazuh-core/common/services/initialization/types.ts +++ b/plugins/wazuh-core/common/services/initialization/types.ts @@ -1,21 +1,13 @@ -export type InitializationTaskRunStatusNotStarted = 'not_started'; -export type InitializationTaskRunStatusRunning = 'running'; -export type InitializationTaskRunStatusFinished = 'finished'; -export type InitializationTaskRunStatus = - | InitializationTaskRunStatusNotStarted - | InitializationTaskRunStatusRunning - | InitializationTaskRunStatusFinished; +import { INITIALIZATION_TASK } from './constants'; -export type InitializationTaskRunResultNull = null; -export type InitializationTaskRunResultSuccess = 'success'; -export type InitializationTaskRunResultFail = 'fail'; -export type InitializationTaskRunResult = - | InitializationTaskRunResultSuccess - | InitializationTaskRunResultFail - | InitializationTaskRunResultNull; +type RunStatusEnum = (typeof INITIALIZATION_TASK)['RUN_STATUS']; -export type InitializationTaskContextInternal = 'internal'; -export type InitializationTaskContextUser = 'user'; -export type InitializationTaskContext = - | InitializationTaskContextInternal - | InitializationTaskContextUser; +export type InitializationTaskRunStatus = RunStatusEnum[keyof RunStatusEnum]; + +type RunResultEnum = (typeof INITIALIZATION_TASK)['RUN_RESULT']; + +export type InitializationTaskRunResult = RunResultEnum[keyof RunResultEnum]; + +type ContextEnum = (typeof INITIALIZATION_TASK)['CONTEXT']; + +export type InitializationTaskContext = ContextEnum[keyof ContextEnum]; From b993f5905d84a8e6e4fbb5e5996225acef0b0d58 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Fri, 29 Nov 2024 10:57:54 +0100 Subject: [PATCH 27/30] fix(initialization): adapt initialization task to new constants --- .../services/initialization/initialization.ts | 4 ++-- .../initialization/lib/initialization-task.ts | 23 +++++++------------ 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index f47ae76c97..636ef63192 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -5,7 +5,7 @@ import { InitializationTaskContext, } from './types'; import { addRoutes } from './routes'; -import { INITIALIZATION_TASK_CONTEXT_INTERNAL } from '../../../common/services/initialization/constants'; +import { INITIALIZATION_TASK } from '../../../common/services/initialization/constants'; import { InitializationTask } from './lib/initialization-task'; export class InitializationService implements IInitializationService { @@ -57,7 +57,7 @@ export class InitializationService implements IInitializationService { return { ...this.services, ...context, scope }; } async runAsInternal(taskNames?: string[]) { - const ctx = this.createRunContext(INITIALIZATION_TASK_CONTEXT_INTERNAL, { + const ctx = this.createRunContext(INITIALIZATION_TASK.CONTEXT.INTERNAL, { core: this._coreStart, }); return await this.run(ctx, taskNames); diff --git a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts index 166d294e45..a6c00c71fd 100644 --- a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts +++ b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts @@ -3,22 +3,15 @@ import { InitializationTaskRunData, IInitializationTask, } from '../types'; -import { - INITIALIZATION_TASK_RUN_RESULT_FAIL, - INITIALIZATION_TASK_RUN_RESULT_NULL, - INITIALIZATION_TASK_RUN_RESULT_SUCCESS, - INITIALIZATION_TASK_RUN_STATUS_FINISHED, - INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED, - INITIALIZATION_TASK_RUN_STATUS_RUNNING, -} from '../../../../common/services/initialization/constants'; +import { INITIALIZATION_TASK } from '../../../../common/services/initialization/constants'; export class InitializationTask implements IInitializationTask { public name: string; private _run: any; public status: InitializationTaskRunData['status'] = - INITIALIZATION_TASK_RUN_STATUS_NOT_STARTED; + INITIALIZATION_TASK.RUN_STATUS.NOT_STARTED; public result: InitializationTaskRunData['result'] = - INITIALIZATION_TASK_RUN_RESULT_NULL; + INITIALIZATION_TASK.RUN_RESULT.NULL; public data: any = null; public createdAt: InitializationTaskRunData['createdAt'] = new Date().toISOString(); @@ -31,7 +24,7 @@ export class InitializationTask implements IInitializationTask { this._run = task.run; } private init() { - this.status = INITIALIZATION_TASK_RUN_STATUS_RUNNING; + this.status = INITIALIZATION_TASK.RUN_STATUS.RUNNING; this.result = null; this.data = null; this.startedAt = new Date().toISOString(); @@ -40,20 +33,20 @@ export class InitializationTask implements IInitializationTask { this.error = null; } async run(...params) { - if (this.status === INITIALIZATION_TASK_RUN_STATUS_RUNNING) { + if (this.status === INITIALIZATION_TASK.RUN_STATUS.RUNNING) { throw new Error(`Another instance of task ${this.name} is running`); } let error; try { this.init(); this.data = await this._run(...params); - this.result = INITIALIZATION_TASK_RUN_RESULT_SUCCESS; + this.result = INITIALIZATION_TASK.RUN_RESULT.SUCCESS; } catch (e) { error = e; - this.result = INITIALIZATION_TASK_RUN_RESULT_FAIL; + this.result = INITIALIZATION_TASK.RUN_RESULT.FAIL; this.error = e.message; } finally { - this.status = INITIALIZATION_TASK_RUN_STATUS_FINISHED; + this.status = INITIALIZATION_TASK.RUN_STATUS.FINISHED; this.finishedAt = new Date().toISOString(); const dateStartedAt = new Date(this.startedAt!); const dateFinishedAt = new Date(this.finishedAt); From 57e345e56abceb2deb2a310aec1b9a61e789918c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 2 Dec 2024 13:59:00 +0100 Subject: [PATCH 28/30] fix(initlization): lint --- .eslintrc.js | 8 + ...e-vulnerabilities-states-index-pattern.tsx | 32 ++- .../react-services/navigation-service.tsx | 93 ++++---- .../server/initialization/index-patterns.ts | 200 ++++++++++-------- .../server/initialization/server-api.test.ts | 14 +- .../server/initialization/server-api.ts | 159 ++++++++------ .../server/initialization/settings.ts | 162 +++++++------- .../server/initialization/templates.ts | 123 ++++++----- plugins/wazuh-core/server/plugin.ts | 83 ++++---- .../services/initialization/initialization.ts | 48 +++-- .../initialization/lib/initialization-task.ts | 47 ++-- .../server/services/initialization/routes.ts | 92 ++++---- .../server/services/initialization/types.ts | 16 +- plugins/wazuh-core/server/types.ts | 6 +- 14 files changed, 620 insertions(+), 463 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 3309297533..28118e1374 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -28,6 +28,7 @@ module.exports = { 'react-hooks', '@typescript-eslint', 'unicorn', + 'import', 'prettier', '@stylistic', ], @@ -210,6 +211,12 @@ module.exports = { '@typescript-eslint/naming-convention': [ 'error', { selector: 'default', format: ['camelCase'] }, + { selector: 'import', format: ['camelCase', 'PascalCase'] }, + { + selector: 'variable', + types: ['function'], + format: ['camelCase', 'PascalCase'], + }, { selector: ['objectLiteralProperty', 'typeProperty'], format: null, @@ -225,6 +232,7 @@ module.exports = { { selector: ['variable'], modifiers: ['global'], + types: ['number', 'string'], format: ['UPPER_CASE'], }, { diff --git a/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx b/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx index c5c819eab2..98aa57da9d 100644 --- a/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx +++ b/plugins/main/public/components/overview/vulnerabilities/common/hocs/validate-vulnerabilities-states-index-pattern.tsx @@ -1,15 +1,15 @@ import React from 'react'; import { compose } from 'redux'; import { connect } from 'react-redux'; +import { EuiButton, EuiEmptyPrompt, EuiLink } from '@elastic/eui'; import { withGuardAsync } from '../../../../common/hocs'; import { getSavedObjects } from '../../../../../kibana-services'; import { SavedObject } from '../../../../../react-services'; import { NOT_TIME_FIELD_NAME_INDEX_PATTERN } from '../../../../../../common/constants'; -import { EuiButton, EuiEmptyPrompt, EuiLink } from '@elastic/eui'; import { webDocumentationLink } from '../../../../../../common/services/web_documentation'; import { vulnerabilityDetection } from '../../../../../utils/applications'; import { LoadingSpinnerDataSource } from '../../../../common/loading/loading-spinner-data-source'; -import NavigationService from '../../../../../react-services/navigation-service'; +import { NavigationService } from '../../../../../react-services/navigation-service'; const INDEX_PATTERN_CREATION_NO_INDEX = 'INDEX_PATTERN_CREATION_NO_INDEX'; @@ -20,8 +20,9 @@ async function checkExistenceIndexPattern(indexPatternID: string) { async function checkExistenceIndices(indexPatternId: string) { try { const fields = await SavedObject.getIndicesFields(indexPatternId); + return { exist: true, fields }; - } catch (error) { + } catch { return { exist: false }; } } @@ -51,7 +52,7 @@ export async function validateVulnerabilitiesStateDataSources({ try { // Check the existence of related index pattern const existIndexPattern = await checkExistenceIndexPattern(indexPatternID); - let indexPattern = existIndexPattern; + const indexPattern = existIndexPattern; // If the idnex pattern does not exist, then check the existence of index if (existIndexPattern?.error?.statusCode === 404) { @@ -70,11 +71,13 @@ export async function validateVulnerabilitiesStateDataSources({ }, }; } + // If the some index match the index pattern, then create the index pattern const resultCreateIndexPattern = await createIndexPattern( indexPatternID, fields, ); + if (resultCreateIndexPattern?.error) { return { ok: true, @@ -86,6 +89,7 @@ export async function validateVulnerabilitiesStateDataSources({ }, }; } + /* WORKAROUND: Redirect to the root of Vulnerabilities Detection application that should redirects to the Dashboard tab. We want to redirect to this view, because we need the component is visible (visualizations) to ensure the process that defines the filters for the @@ -95,6 +99,7 @@ export async function validateVulnerabilitiesStateDataSources({ */ NavigationService.getInstance().navigateToApp(vulnerabilityDetection.id); } + return { ok: false, data: { indexPattern }, @@ -127,10 +132,13 @@ const errorPromptBody = { ), }; -export const PromptCheckIndex = props => { +export const PromptCheckIndex = (props: { + error: { title: string; message: string; type?: string }; + refresh: () => void; +}) => { const { refresh } = props; - const { title, message } = props?.error; - const body = errorPromptBody?.[props?.error?.type] ||

{message}

; + const { title, message } = props.error; + const body = errorPromptBody?.[props.error?.type] ||

{message}

; return ( { ); }; -const mapStateToProps = state => ({ - vulnerabilitiesStatesindexPatternID: - state.appConfig.data['vulnerabilities.pattern'], -}); +const mapStateToProps = state => { + return { + vulnerabilitiesStatesindexPatternID: + state.appConfig.data['vulnerabilities.pattern'], + }; +}; export const withVulnerabilitiesStateDataSource = compose( connect(mapStateToProps), diff --git a/plugins/main/public/react-services/navigation-service.tsx b/plugins/main/public/react-services/navigation-service.tsx index 8c0a032e51..5e001a9ecd 100644 --- a/plugins/main/public/react-services/navigation-service.tsx +++ b/plugins/main/public/react-services/navigation-service.tsx @@ -1,13 +1,14 @@ import { Location, Action, History } from 'history'; +import rison from 'rison-node'; import { getCore } from '../kibana-services'; import { NavigateToAppOptions } from '../../../../src/core/public'; -import { getIndexPattern } from './elastic_helpers'; import { buildPhraseFilter } from '../../../../src/plugins/data/common'; -import rison from 'rison-node'; +import { getIndexPattern } from './elastic_helpers'; class NavigationService { + // eslint-disable-next-line no-use-before-define private static instance: NavigationService; - private history: History; + private readonly history: History; private constructor(history: History) { this.history = history; @@ -19,6 +20,7 @@ class NavigationService { } else if (!NavigationService.instance) { throw new Error('NavigationService must be initialized with a history.'); } + return NavigationService.instance; } @@ -56,30 +58,31 @@ class NavigationService { ? this.buildSearch(params) : this.buildSearch(this.getParams()); const locationHash = this.getHash(); + this.navigate( `${newPath}${queryParams ? `?${queryParams}` : ''}${locationHash}`, ); } public navigate(path: string, state?: any): void { - if (!state) { - this.history.push(path); - } else { + if (state) { this.history.push({ pathname: path, state, }); + } else { + this.history.push(path); } } public replace(path: string, state?: any): void { - if (!state) { - this.history.replace(path); - } else { + if (state) { this.history.replace({ pathname: path, state, }); + } else { + this.history.replace(path); } } @@ -96,13 +99,14 @@ class NavigationService { } public reload(): void { - window.location.reload(); + globalThis.location.reload(); } public listen( listener: (location: Location, action: Action) => void, ): () => void { const unlisten = this.history.listen(listener); + return unlisten; } @@ -125,26 +129,27 @@ class NavigationService { } public buildSearch(search: URLSearchParams) { - return Array.from(search.entries()) + return [...search.entries()] .map(([key, value]) => `${key}=${value}`) .join('&'); } - public updateAndNavigateSearchParams(params: { - [key: string]: string | null; - }): void { + public updateAndNavigateSearchParams( + params: Record, + ): void { const urlParams = this.getParams(); // Update or delete parameters according to their value - Object.entries(params).forEach(([key, value]) => { + for (const [key, value] of Object.entries(params)) { if (value === null) { urlParams.delete(key); } else { urlParams.set(key, value); } - }); + } const queryString = this.buildSearch(urlParams); + this.navigate(`${this.getPathname()}?${queryString}`); } @@ -152,16 +157,17 @@ class NavigationService { this.updateAndNavigateSearchParams({ tab: newTab }); } - public switchSubTab = (subTab: string): void => { + public switchSubTab(subTab: string): void { this.updateAndNavigateSearchParams({ tabView: subTab }); - }; + } /* - TODO: Analyze and improve this function taking into account whether buildFilter_w is still used and whether the implementation with respect to the middle button is correct in navigateToModule + TODO: Analyze and improve this function taking into account whether buildFilterW is still used and whether the implementation with respect to the middle button is correct in navigateToModule */ - private buildFilter_w(filters, indexPattern) { + private buildFilterW(filters, indexPattern) { const filtersArray: any[] = []; - Object.keys(filters).forEach(currentFilter => { + + for (const currentFilter of Object.keys(filters)) { filtersArray.push({ ...buildPhraseFilter( { name: currentFilter, type: 'text' }, @@ -170,41 +176,51 @@ class NavigationService { ), $state: { isImplicit: false, store: 'appState' }, }); - }); + } + return rison.encode({ filters: filtersArray }); } - navigateToModule(e: any, section: string, params: any, navigateMethod?: any) { - e.persist(); // needed to access this event asynchronously - if (e.button == 0) { - // left button clicked - if (navigateMethod) { - navigateMethod(); - return; - } + navigateToModule( + event: any, + section: string, + params: any, + navigateMethod?: any, + ) { + event.persist(); // needed to access this event asynchronously + + if ( + event.button === 0 && // left button clicked + navigateMethod + ) { + navigateMethod(); + + return; } + getIndexPattern().then(indexPattern => { const urlParams = {}; - if (Object.keys(params).length) { - Object.keys(params).forEach(key => { + if (Object.keys(params).length > 0) { + for (const key of Object.keys(params)) { if (key === 'filters') { - urlParams['_w'] = this.buildFilter_w(params[key], indexPattern); + urlParams['_w'] = this.buildFilterW(params[key], indexPattern); } else { urlParams[key] = params[key]; } - }); + } } + const url = Object.entries(urlParams) - .map(e => e.join('=')) + .map(urlParam => urlParam.join('=')) .join('&'); - const currentUrl = window.location.href.split('#/')[0]; + const currentUrl = globalThis.location.href.split('#/')[0]; const newUrl = currentUrl + `#/${section}?` + url; - if (e && (e.which == 2 || e.button == 1)) { + if (event && (event.which === 2 || event.button === 1)) { // middlebutton clicked window.open(newUrl, '_blank', 'noreferrer'); - } else if (e.button == 0) { + } else if (event.button === 0) { // left button clicked if (navigateMethod) { navigateMethod(); @@ -217,3 +233,4 @@ class NavigationService { } export default NavigationService; +export { NavigationService }; diff --git a/plugins/wazuh-core/server/initialization/index-patterns.ts b/plugins/wazuh-core/server/initialization/index-patterns.ts index 012f8be2a8..42b4e73f57 100644 --- a/plugins/wazuh-core/server/initialization/index-patterns.ts +++ b/plugins/wazuh-core/server/initialization/index-patterns.ts @@ -4,63 +4,32 @@ import { InitializationTaskRunContext, } from '../services'; -interface ensureIndexPatternExistenceContextTask { +interface EnsureIndexPatternExistenceContextTask { indexPatternID: string; options: any; } -interface ensureIndexPatternExistenceContextTaskWithConfigurationSetting - extends ensureIndexPatternExistenceContextTask { +interface EnsureIndexPatternExistenceContextTaskWithConfigurationSetting + extends EnsureIndexPatternExistenceContextTask { configurationSettingKey: string; } -const decoratorCheckIsEnabled = fn => { - return async ( +// eslint-disable-next-line @typescript-eslint/no-unused-vars +const decoratorCheckIsEnabled = + callback => + async ( ctx: InitializationTaskRunContext, { configurationSettingKey, ...ctxTask - }: ensureIndexPatternExistenceContextTaskWithConfigurationSetting, + }: EnsureIndexPatternExistenceContextTaskWithConfigurationSetting, ) => { if (await ctx.configuration.get(configurationSettingKey)) { - await fn(ctx, ctxTask); + await callback(ctx, ctxTask); } else { ctx.logger.info(`Check [${configurationSettingKey}]: disabled. Skipped.`); } }; -}; - -export const ensureIndexPatternExistence = async ( - { logger, savedObjectsClient, indexPatternsClient }, - { indexPatternID, options = {} }: ensureIndexPatternExistenceContextTask, -) => { - try { - logger.debug( - `Checking existence of index pattern with ID [${indexPatternID}]`, - ); - const response = await savedObjectsClient.get( - 'index-pattern', - indexPatternID, - ); - logger.debug(`Index pattern with ID [${indexPatternID}] exists`); - return response; - } catch (error) { - // Get not found saved object - if (error?.output?.statusCode === 404) { - // Create index pattern - logger.info(`Index pattern with ID [${indexPatternID}] does not exist`); - return await createIndexPattern( - { logger, savedObjectsClient, indexPatternsClient }, - indexPatternID, - options, - ); - } else { - throw new Error( - `index pattern with ID [${indexPatternID}] existence could not be checked due to: ${error.message}`, - ); - } - } -}; async function getFieldMappings( { logger, indexPatternsClient }, @@ -74,11 +43,13 @@ async function getFieldMappings( // meta_fields=_source&meta_fields=_id&meta_fields=_type&meta_fields=_index&meta_fields=_score metaFields: ['_source', '_id', '_type', '_index', '_score'], }); + logger.debug( `Fields for index pattern with title [${indexPatternTitle}]: ${JSON.stringify( fields, )}`, ); + return fields; } @@ -87,30 +58,32 @@ async function createIndexPattern( indexPatternID, options: { fieldsNoIndices?: any; - savedObjectOverwrite?: { [key: string]: any }; + savedObjectOverwrite?: Record; } = {}, ) { try { let fields; + try { fields = await getFieldMappings( { logger, indexPatternsClient }, indexPatternID, ); - } catch (e) { - if (e?.output?.statusCode === 404 && options.fieldsNoIndices) { + } catch (error) { + if (error?.output?.statusCode === 404 && options.fieldsNoIndices) { const message = `Fields for index pattern with ID [${indexPatternID}] could not be obtained. This could indicate there are not matching indices because they were not generated or there is some error in the process that generates and indexes that data. The index pattern will be created with a set of pre-defined fields.`; + logger.warn(message); fields = options.fieldsNoIndices; } else { - throw e; + throw error; } } const savedObjectData = { title: indexPatternID, fields: JSON.stringify(fields), - ...(options?.savedObjectOverwrite || {}), + ...options?.savedObjectOverwrite, }; logger.debug( @@ -126,9 +99,10 @@ async function createIndexPattern( refresh: true, }, ); - const indexPatternCreatedMessage = `Created index pattern with ID [${response.id}] title [${response.attributes.title}]`; + logger.info(indexPatternCreatedMessage); + return response; } catch (error) { throw new Error( @@ -137,21 +111,60 @@ async function createIndexPattern( } } +export const ensureIndexPatternExistence = async ( + { logger, savedObjectsClient, indexPatternsClient }, + { indexPatternID, options = {} }: EnsureIndexPatternExistenceContextTask, +) => { + try { + logger.debug( + `Checking existence of index pattern with ID [${indexPatternID}]`, + ); + + const response = await savedObjectsClient.get( + 'index-pattern', + indexPatternID, + ); + + logger.debug(`Index pattern with ID [${indexPatternID}] exists`); + + return response; + } catch (error) { + // Get not found saved object + if (error?.output?.statusCode === 404) { + // Create index pattern + logger.info(`Index pattern with ID [${indexPatternID}] does not exist`); + + return await createIndexPattern( + { logger, savedObjectsClient, indexPatternsClient }, + indexPatternID, + options, + ); + } else { + throw new Error( + `index pattern with ID [${indexPatternID}] existence could not be checked due to: ${error.message}`, + ); + } + } +}; + function getSavedObjectsClient( ctx: InitializationTaskRunContext, scope: InitializationTaskContext, ) { switch (scope) { - case 'internal': + case 'internal': { return ctx.core.savedObjects.createInternalRepository(); - break; - case 'user': + } + + case 'user': { return ctx.core.savedObjects.savedObjectsStart.getScopedClient( ctx.request, ); + } + + default: { break; - default: - break; + } } } @@ -160,18 +173,21 @@ function getIndexPatternsClient( scope: InitializationTaskContext, ) { switch (scope) { - case 'internal': + case 'internal': { return new IndexPatternsFetcher( ctx.core.opensearch.legacy.client.callAsInternalUser, ); - break; - case 'user': + } + + case 'user': { return new IndexPatternsFetcher( ctx.core.opensearch.legacy.client.callAsCurrentUser, ); + } + + default: { break; - default: - break; + } } } @@ -181,14 +197,17 @@ function getIndexPatternID( rest: any, ) { switch (scope) { - case 'internal': + case 'internal': { return rest.getIndexPatternID(ctx); - break; - case 'user': + } + + case 'user': { return ctx.getIndexPatternID(ctx); + } + + default: { break; - default: - break; + } } } @@ -200,32 +219,37 @@ export const initializationTaskCreatorIndexPattern = ({ }: { getIndexPatternID: (ctx: any) => Promise; taskName: string; + // eslint-disable-next-line @typescript-eslint/no-empty-object-type options: {}; configurationSettingKey: string; -}) => ({ - name: taskName, - async run(ctx: InitializationTaskRunContext) { - let indexPatternID; - try { - ctx.logger.debug('Starting index pattern saved object'); - indexPatternID = await getIndexPatternID(ctx, ctx.scope, rest); - - // Get clients depending on the scope - const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); - const indexPatternsClient = getIndexPatternsClient(ctx, ctx.scope); - - return await ensureIndexPatternExistence( - { ...ctx, indexPatternsClient, savedObjectsClient }, - { - indexPatternID, - options, - configurationSettingKey, - }, - ); - } catch (error) { - const message = `Error initilizating index pattern with ID [${indexPatternID}]: ${error.message}`; - ctx.logger.error(message); - throw new Error(message); - } - }, -}); +}) => { + return { + name: taskName, + async run(ctx: InitializationTaskRunContext) { + let indexPatternID; + + try { + ctx.logger.debug('Starting index pattern saved object'); + indexPatternID = await getIndexPatternID(ctx, ctx.scope, rest); + + // Get clients depending on the scope + const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); + const indexPatternsClient = getIndexPatternsClient(ctx, ctx.scope); + + return await ensureIndexPatternExistence( + { ...ctx, indexPatternsClient, savedObjectsClient }, + { + indexPatternID, + options, + configurationSettingKey, + }, + ); + } catch (error) { + const message = `Error initilizating index pattern with ID [${indexPatternID}]: ${error.message}`; + + ctx.logger.error(message); + throw new Error(message); + } + }, + }; +}; diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index dfe1e20c13..cb1aec5090 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -45,6 +45,7 @@ describe('ServerAPIConnectionCompatibility', () => { `Check server API connection and compatibility for the server API hosts`, async ({ apiHostID, apiVersionResponse, isCompatible }) => { const loggerMock = jest.fn(); + await ServerAPIConnectionCompatibility( { manageHosts: { @@ -58,11 +59,13 @@ describe('ServerAPIConnectionCompatibility', () => { }, serverAPIClient: { asInternalUser: { - request: () => ({ - data: { - data: apiVersionResponse, - }, - }), + request: () => { + return { + data: { + data: apiVersionResponse, + }, + }; + }, }, }, }, @@ -72,6 +75,7 @@ describe('ServerAPIConnectionCompatibility', () => { expect(loggerMock).toHaveBeenCalledWith( `Checking the connection and compatibility with server API [${apiHostID}]`, ); + if (apiVersionResponse.api_version) { if (isCompatible === true) { expect(loggerMock).toHaveBeenCalledWith( diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index ab92208203..d6b15b868c 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -6,112 +6,131 @@ import { webDocumentationLink } from '../../common/services/web_documentation'; import { version as appVersion } from '../../package.json'; import { InitializationTaskRunContext } from '../services'; -export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ - taskName, -}: { - taskName: string; -}) => ({ - name: taskName, - async run(ctx: InitializationTaskRunContext) { - try { - ctx.logger.debug( - 'Starting check server API connection and compatibility', - ); - const results = await ServersAPIConnectionCompatibility(ctx); - ctx.logger.info( - 'Start check server API connection and compatibility finished', - ); - return results; - } catch (error) { - const message = `Error checking server API connection and compatibility: ${error.message}`; - ctx.logger.error(message); - throw new Error(message); - } - }, -}); - -async function ServersAPIConnectionCompatibility( - ctx: InitializationTaskRunContext, +export function checkAppServerCompatibility( + appVersion: string, + serverAPIVersion: string, ) { - if (ctx.scope === 'user' && ctx.request?.query?.apiHostID) { - const host = await ctx.manageHosts.get(ctx.request.query.apiHostID, { - excludePassword: true, - }); - - ctx.logger.debug(`APP version [${appVersion}]`); - - return await ServerAPIConnectionCompatibility(ctx, host.id, appVersion); - } else { - const hosts = await ctx.manageHosts.get(undefined, { - excludePassword: true, - }); - - ctx.logger.debug(`APP version [${appVersion}]`); + const api = /v?(?\d+)\.(?\d+)\.(?\d+)/.exec( + serverAPIVersion, + ); + const [appVersionMajor, appVersionMinor] = appVersion.split('.'); - return await Promise.all( - hosts.map(async ({ id: apiHostID }: { id: string }) => - ServerAPIConnectionCompatibility(ctx, apiHostID, appVersion), - ), - ); - } + return ( + api?.groups?.major === appVersionMajor && + api?.groups?.minor === appVersionMinor + ); } -export async function ServerAPIConnectionCompatibility( +export async function serverAPIConnectionCompatibility( ctx: InitializationTaskRunContext, apiHostID: string, appVersion: string, ) { let connection = null, compatibility = null, - api_version = null; + apiVersion = null; + try { ctx.logger.debug( `Checking the connection and compatibility with server API [${apiHostID}]`, ); + const response = await ctx.serverAPIClient.asInternalUser.request( 'GET', '/', {}, { apiHostID }, ); + connection = true; - api_version = response?.data?.data?.api_version; - if (!api_version) { + apiVersion = response?.data?.data?.api_version; + + if (!apiVersion) { throw new Error('version is not found in the response of server API'); } - ctx.logger.debug(`Server API version [${api_version}]`); - if (!checkAppServerCompatibility(appVersion, api_version)) { + + ctx.logger.debug(`Server API version [${apiVersion}]`); + + if (checkAppServerCompatibility(appVersion, apiVersion)) { + compatibility = true; + ctx.logger.info( + `Server API [${apiHostID}] version [${apiVersion}] is compatible with the ${PLUGIN_APP_NAME} version`, + ); + } else { compatibility = false; ctx.logger.warn( - `Server API [${apiHostID}] version [${api_version}] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( + `Server API [${apiHostID}] version [${apiVersion}] is not compatible with the ${PLUGIN_APP_NAME} version [${appVersion}]. Major and minor number must match at least. It is recommended the server API and ${PLUGIN_APP_NAME} version are equals. Read more about this error in our troubleshooting guide: ${webDocumentationLink( PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, )}.`, ); - } else { - compatibility = true; - ctx.logger.info( - `Server API [${apiHostID}] version [${api_version}] is compatible with the ${PLUGIN_APP_NAME} version`, - ); } } catch (error) { ctx.logger.warn( `Error checking the connection and compatibility with server API [${apiHostID}]: ${error.message}`, ); } finally { - return { connection, compatibility, api_version, id: apiHostID }; + // eslint-disable-next-line no-unsafe-finally + return { + connection, + compatibility, + api_version: apiVersion, + id: apiHostID, + }; } } -export function checkAppServerCompatibility( - appVersion: string, - serverAPIVersion: string, +async function serversAPIConnectionCompatibility( + ctx: InitializationTaskRunContext, ) { - const api = /v?(?\d+)\.(?\d+)\.(?\d+)/.exec( - serverAPIVersion, - ); - const [appVersionMajor, appVersionMinor] = appVersion.split('.'); - return ( - api?.groups?.major === appVersionMajor && - api?.groups?.minor === appVersionMinor - ); + if (ctx.scope === 'user' && ctx.request?.query?.apiHostID) { + const host = await ctx.manageHosts.get(ctx.request.query.apiHostID, { + excludePassword: true, + }); + + ctx.logger.debug(`APP version [${appVersion}]`); + + return await serverAPIConnectionCompatibility(ctx, host.id, appVersion); + } else { + const hosts = await ctx.manageHosts.get(undefined, { + excludePassword: true, + }); + + ctx.logger.debug(`APP version [${appVersion}]`); + + return await Promise.all( + hosts.map(async ({ id: apiHostID }: { id: string }) => + serverAPIConnectionCompatibility(ctx, apiHostID, appVersion), + ), + ); + } } + +export const initializationTaskCreatorServerAPIConnectionCompatibility = ({ + taskName, +}: { + taskName: string; +}) => { + return { + name: taskName, + async run(ctx: InitializationTaskRunContext) { + try { + ctx.logger.debug( + 'Starting check server API connection and compatibility', + ); + + const results = await serversAPIConnectionCompatibility(ctx); + + ctx.logger.info( + 'Start check server API connection and compatibility finished', + ); + + return results; + } catch (error) { + const message = `Error checking server API connection and compatibility: ${error.message}`; + + ctx.logger.error(message); + throw new Error(message); + } + }, + }; +}; diff --git a/plugins/wazuh-core/server/initialization/settings.ts b/plugins/wazuh-core/server/initialization/settings.ts index 4c92d31663..2391cec165 100644 --- a/plugins/wazuh-core/server/initialization/settings.ts +++ b/plugins/wazuh-core/server/initialization/settings.ts @@ -13,14 +13,15 @@ */ import { isEqual } from 'lodash'; +import { IUiSettingsClient } from 'src/core/server'; import { InitializationTaskContext, InitializationTaskRunContext, } from '../services'; -import { IUiSettingsClient } from 'src/core/server'; -const decoratorCheckIsEnabled = fn => { - return async ( +const decoratorCheckIsEnabled = + callback => + async ( ctx: InitializationTaskRunContext, { configurationSetting, @@ -28,12 +29,41 @@ const decoratorCheckIsEnabled = fn => { }: { key: string; value: any; configurationSetting: string }, ) => { if (await ctx.configuration.get(configurationSetting)) { - await fn(ctx, ctxTask); + await callback(ctx, ctxTask); } else { ctx.logger.info(`Check [${configurationSetting}]: disabled. Skipped.`); } }; -}; + +function stringifySetting(setting: any) { + try { + return JSON.stringify(setting); + } catch { + return setting; + } +} + +async function updateSetting( + uiSettingsClient: IUiSettingsClient, + pluginPlatformSettingName: string, + defaultAppValue: any, + retries = 3, +): Promise { + return await uiSettingsClient + .set(pluginPlatformSettingName, defaultAppValue) + .catch(async error => { + if (retries > 0) { + return await updateSetting( + uiSettingsClient, + pluginPlatformSettingName, + defaultAppValue, + --retries, + ); + } + + throw error; + }); +} export const checkPluginPlatformSettings = decoratorCheckIsEnabled( async ( @@ -47,6 +77,7 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( }: { key: string; value: any }, ) => { logger.debug(`Getting setting [${pluginPlatformSettingName}]...`); + const valuePluginPlatformSetting = await uiSettingsClient.get( pluginPlatformSettingName, ); @@ -54,6 +85,7 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( valuePluginPlatformSetting, defaultAppValue, ); + logger.debug( `Check setting [${pluginPlatformSettingName}]: ${stringifySetting( valuePluginPlatformSetting, @@ -74,6 +106,7 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( valuePluginPlatformSetting ? 'yes' : 'no' }`, ); + if (!valuePluginPlatformSetting || settingsAreDifferent) { logger.debug(`Updating [${pluginPlatformSettingName}] setting...`); await updateSetting( @@ -90,48 +123,24 @@ export const checkPluginPlatformSettings = decoratorCheckIsEnabled( }, ); -async function updateSetting( - uiSettingsClient: IUiSettingsClient, - pluginPlatformSettingName: string, - defaultAppValue: any, - retries: number = 3, -): Promise { - return await uiSettingsClient - .set(pluginPlatformSettingName, defaultAppValue) - .catch(async error => { - if (retries > 0) { - return await updateSetting( - uiSettingsClient, - pluginPlatformSettingName, - defaultAppValue, - --retries, - ); - } - throw error; - }); -} - -function stringifySetting(setting: any) { - try { - return JSON.stringify(setting); - } catch (error) { - return setting; - } -} - function getSavedObjectsClient( ctx: InitializationTaskRunContext, scope: InitializationTaskContext, ) { switch (scope) { - case 'internal': + case 'internal': { return ctx.core.savedObjects.createInternalRepository(); - case 'user': + } + + case 'user': { return ctx.core.savedObjects.savedObjectsStart.getScopedClient( ctx.request, ); - default: + } + + default: { break; + } } } @@ -141,53 +150,58 @@ function getUiSettingsClient( client: any, ) { switch (scope) { - case 'internal': + case 'internal': { return ctx.core.uiSettings.asScopedToClient(client); + } - case 'user': + case 'user': { return ctx.core.uiSettings.uiSettingsStart.asScopedToClient(client); + } - default: + default: { break; + } } } export const initializationTaskCreatorSetting = ( setting: { key: string; value: any; configurationSetting: string }, taskName: string, -) => ({ - name: taskName, - async run(ctx: InitializationTaskRunContext) { - try { - ctx.logger.debug('Starting setting'); - - // Get clients depending on the scope - const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); - const uiSettingsClient = getUiSettingsClient( - ctx, - ctx.scope, - savedObjectsClient, - ); +) => { + return { + name: taskName, + async run(ctx: InitializationTaskRunContext) { + try { + ctx.logger.debug('Starting setting'); - const { key, value, configurationSetting } = setting; + // Get clients depending on the scope + const savedObjectsClient = getSavedObjectsClient(ctx, ctx.scope); + const uiSettingsClient = getUiSettingsClient( + ctx, + ctx.scope, + savedObjectsClient, + ); + const { key, value, configurationSetting } = setting; - await checkPluginPlatformSettings( - { - logger: ctx.logger, - uiSettingsClient, - configuration: ctx.configuration, - }, - { - key, - value, - configurationSetting, - }, - ); - ctx.logger.info('Start setting finished'); - } catch (error) { - const message = `Error initilizating setting [${setting.key}]: ${error.message}`; - ctx.logger.error(message); - throw new Error(message); - } - }, -}); + await checkPluginPlatformSettings( + { + logger: ctx.logger, + uiSettingsClient, + configuration: ctx.configuration, + }, + { + key, + value, + configurationSetting, + }, + ); + ctx.logger.info('Start setting finished'); + } catch (error) { + const message = `Error initilizating setting [${setting.key}]: ${error.message}`; + + ctx.logger.error(message); + throw new Error(message); + } + }, + }; +}; diff --git a/plugins/wazuh-core/server/initialization/templates.ts b/plugins/wazuh-core/server/initialization/templates.ts index 085cfb8d2c..2afb6d044f 100644 --- a/plugins/wazuh-core/server/initialization/templates.ts +++ b/plugins/wazuh-core/server/initialization/templates.ts @@ -1,5 +1,43 @@ import { InitializationTaskRunContext } from '../services'; +export function getTemplateForIndexPattern( + indexPatternTitle: string, + templates: { name: string; index_patterns: string }[], +) { + // eslint-disable-next-line @typescript-eslint/naming-convention + return templates.filter(({ index_patterns }: { index_patterns: string }) => { + const [, cleanIndexPatterns] = index_patterns.match(/\[(.+)]/) || [ + null, + null, + ]; + + if (!cleanIndexPatterns) { + return false; + } + + const indexPatterns = cleanIndexPatterns.match(/([^\s,]+)/g); + + if (!indexPatterns) { + return false; + } + + const lastChar = indexPatternTitle.at(-1); + const indexPatternTitleCleaned = + lastChar === '*' ? indexPatternTitle.slice(0, -1) : indexPatternTitle; + + return indexPatterns.some(indexPattern => { + const lastChar = indexPattern.at(-1); + const indexPatternCleaned = + lastChar === '*' ? indexPattern.slice(0, -1) : indexPattern; + + return ( + indexPatternCleaned.includes(indexPatternTitleCleaned) || + indexPatternTitleCleaned.includes(indexPatternCleaned) + ); + }); + }); +} + export const checkIndexPatternHasTemplate = async ( { logger }: InitializationTaskRunContext, { @@ -8,16 +46,19 @@ export const checkIndexPatternHasTemplate = async ( }: { indexPatternTitle: string; opensearchClient: any }, ) => { logger.debug('Getting templates'); + const data = await opensearchClient.cat.templates({ format: 'json' }); logger.debug( 'Checking the index pattern with title [${indexPatternTitle}] has defined some template', ); + const templatesFound = getTemplateForIndexPattern( indexPatternTitle, data.body, ); - if (!templatesFound.length) { + + if (templatesFound.length === 0) { throw new Error( `No template found for index pattern with title [${indexPatternTitle}]`, ); @@ -32,39 +73,6 @@ export const checkIndexPatternHasTemplate = async ( ); }; -export function getTemplateForIndexPattern( - indexPatternTitle: string, - templates: { name: string; index_patterns: string }[], -) { - return templates.filter(({ index_patterns }: { index_patterns: string }) => { - const [, cleanIndexPatterns] = index_patterns.match(/\[(.+)\]/) || [ - null, - null, - ]; - if (!cleanIndexPatterns) { - return false; - } - const indexPatterns = cleanIndexPatterns.match(/([^\s,]+)/g); - - if (!indexPatterns) { - return false; - } - - const lastChar = indexPatternTitle[indexPatternTitle.length - 1]; - const indexPatternTitleCleaned = - lastChar === '*' ? indexPatternTitle.slice(0, -1) : indexPatternTitle; - return indexPatterns.some(indexPattern => { - const lastChar = indexPattern[indexPattern.length - 1]; - const indexPatternCleaned = - lastChar === '*' ? indexPattern.slice(0, -1) : indexPattern; - return ( - indexPatternCleaned.includes(indexPatternTitleCleaned) || - indexPatternTitleCleaned.includes(indexPatternCleaned) - ); - }); - }); -} - export const initializationTaskCreatorExistTemplate = ({ getOpenSearchClient, getIndexPatternTitle, @@ -73,24 +81,29 @@ export const initializationTaskCreatorExistTemplate = ({ getOpenSearchClient: (ctx: InitializationTaskRunContext) => any; getIndexPatternTitle: (ctx: InitializationTaskRunContext) => Promise; taskName: string; -}) => ({ - name: taskName, - async run(ctx: InitializationTaskRunContext) { - let indexPatternTitle; - try { - ctx.logger.debug('Starting check of existent template'); - - const opensearchClient = getOpenSearchClient(ctx); - indexPatternTitle = await getIndexPatternTitle(ctx); - await checkIndexPatternHasTemplate(ctx, { - opensearchClient, - indexPatternTitle, - }); - ctx.logger.info('Start check of existent template finished'); - } catch (error) { - const message = `Error checking of existent template for index pattern with title [${indexPatternTitle}]: ${error.message}`; - ctx.logger.error(message); - throw new Error(message); - } - }, -}); +}) => { + return { + name: taskName, + async run(ctx: InitializationTaskRunContext) { + let indexPatternTitle; + + try { + ctx.logger.debug('Starting check of existent template'); + + const opensearchClient = getOpenSearchClient(ctx); + + indexPatternTitle = await getIndexPatternTitle(ctx); + await checkIndexPatternHasTemplate(ctx, { + opensearchClient, + indexPatternTitle, + }); + ctx.logger.info('Start check of existent template finished'); + } catch (error) { + const message = `Error checking of existent template for index pattern with title [${indexPatternTitle}]: ${error.message}`; + + ctx.logger.error(message); + throw new Error(message); + } + }, + }; +}; diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index afb08f0f1a..ea614c532b 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -6,19 +6,6 @@ import { Logger, } from 'opensearch-dashboards/server'; import { validate as validateNodeCronInterval } from 'node-cron'; -import { - PluginSetup, - WazuhCorePluginSetup, - WazuhCorePluginStart, -} from './types'; -import { setCore } from './plugin-services'; -import { - ManageHosts, - createDashboardSecurity, - ServerAPIClient, - ConfigurationStore, - InitializationService, -} from './services'; import { Configuration } from '../common/services/configuration'; import { PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, @@ -32,6 +19,19 @@ import { WAZUH_PLUGIN_PLATFORM_SETTING_METAFIELDS, WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER, } from '../common/constants'; +import { + PluginSetup, + WazuhCorePluginSetup, + WazuhCorePluginStart, +} from './types'; +import { setCore } from './plugin-services'; +import { + ManageHosts, + createDashboardSecurity, + ServerAPIClient, + ConfigurationStore, + InitializationService, +} from './services'; import { enhanceConfiguration } from './services/enhance-configuration'; import { initializationTaskCreatorServerAPIConnectionCompatibility } from './initialization/server-api'; import { @@ -39,19 +39,20 @@ import { initializationTaskCreatorIndexPattern, initializationTaskCreatorSetting, } from './initialization'; -import AlertsIndexPatternDefaultFields from './initialization/index-patterns-fields/alerts-fields.json'; -import MonitoringIndexPatternDefaultFields from './initialization/index-patterns-fields/monitoring-fields.json'; -import StatisticsIndexPatternDefaultFields from './initialization/index-patterns-fields/statistics-fields.json'; -import VulnerabilitiesStatesFields from './initialization/index-patterns-fields/vulnerabibility-states-fields.json'; +import alertsIndexPatternDefaultFields from './initialization/index-patterns-fields/alerts-fields.json'; +import monitoringIndexPatternDefaultFields from './initialization/index-patterns-fields/monitoring-fields.json'; +import statisticsIndexPatternDefaultFields from './initialization/index-patterns-fields/statistics-fields.json'; +import vulnerabilitiesStatesFields from './initialization/index-patterns-fields/vulnerabibility-states-fields.json'; export class WazuhCorePlugin implements Plugin { private readonly logger: Logger; - private services: { [key: string]: any }; - private _internal: { [key: string]: any }; + private readonly services: Record; + // eslint-disable-next-line @typescript-eslint/naming-convention + private readonly _internal: Record; - constructor(private initializerContext: PluginInitializerContext) { + constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); this.services = {}; this._internal = {}; @@ -81,14 +82,14 @@ export class WazuhCorePlugin enhanceConfiguration(this.services.configuration); // Register the plugin settings - Object.entries(PLUGIN_SETTINGS).forEach(([key, value]) => - this.services.configuration.register(key, value), - ); + for (const [key, value] of Object.entries(PLUGIN_SETTINGS)) { + this.services.configuration.register(key, value); + } // Add categories to the configuration - Object.entries(PLUGIN_SETTINGS_CATEGORIES).forEach(([key, value]) => { + for (const [key, value] of Object.entries(PLUGIN_SETTINGS_CATEGORIES)) { this.services.configuration.registerCategory({ ...value, id: key }); - }); + } /* Workaround: Redefine the validation functions of cron.statistics.interval setting. Because the settings are defined in the backend and frontend side using the same definitions, @@ -97,16 +98,20 @@ export class WazuhCorePlugin const setting = this.services.configuration._settings.get( 'cron.statistics.interval', ); - !setting.validateUIForm && - (setting.validateUIForm = function (value) { + + if (!setting.validateUIForm) { + setting.validateUIForm = function (value) { return this.validate(value); - }); - !setting.validate && - (setting.validate = function (value: string) { + }; + } + + if (!setting.validate) { + setting.validate = function (value: string) { return validateNodeCronInterval(value) ? undefined : 'Interval is not valid.'; - }); + }; + } this.services.configuration.setup(); @@ -147,7 +152,7 @@ export class WazuhCorePlugin savedObjectOverwrite: { timeFieldName: 'timestamp', }, - fieldsNoIndices: AlertsIndexPatternDefaultFields, + fieldsNoIndices: alertsIndexPatternDefaultFields, }, configurationSettingKey: 'checks.pattern', }), @@ -163,7 +168,7 @@ export class WazuhCorePlugin savedObjectOverwrite: { timeFieldName: 'timestamp', }, - fieldsNoIndices: MonitoringIndexPatternDefaultFields, + fieldsNoIndices: monitoringIndexPatternDefaultFields, }, configurationSettingKey: 'checks.monitoring', // TODO: create new setting }), @@ -176,7 +181,7 @@ export class WazuhCorePlugin ctx.configuration.get('vulnerabilities.pattern'), taskName: 'index-pattern:vulnerabilities-states', options: { - fieldsNoIndices: VulnerabilitiesStatesFields, + fieldsNoIndices: vulnerabilitiesStatesFields, }, configurationSettingKey: 'checks.vulnerability', // TODO: create new setting }), @@ -191,10 +196,10 @@ export class WazuhCorePlugin 'cron.prefix', 'cron.statistics.index.name', ); - const prefixTemplateName = appConfig['cron.prefix']; const statisticsIndicesTemplateName = appConfig['cron.statistics.index.name']; + return `${prefixTemplateName}-${statisticsIndicesTemplateName}-*`; }, taskName: 'index-pattern:statistics', @@ -202,7 +207,7 @@ export class WazuhCorePlugin savedObjectOverwrite: { timeFieldName: 'timestamp', }, - fieldsNoIndices: StatisticsIndexPatternDefaultFields, + fieldsNoIndices: statisticsIndexPatternDefaultFields, }, configurationSettingKey: 'checks.statistics', // TODO: create new setting }), @@ -210,7 +215,7 @@ export class WazuhCorePlugin // Settings // TODO: this task should be registered by the related plugin - [ + for (const setting of [ { key: PLUGIN_PLATFORM_SETTING_NAME_MAX_BUCKETS, value: WAZUH_PLUGIN_PLATFORM_SETTING_MAX_BUCKETS, @@ -226,11 +231,11 @@ export class WazuhCorePlugin value: JSON.stringify(WAZUH_PLUGIN_PLATFORM_SETTING_TIME_FILTER), configurationSetting: 'checks.timeFilter', }, - ].forEach(setting => { + ]) { this.services.initialization.register( initializationTaskCreatorSetting(setting, `setting:${setting.key}`), ); - }); + } // Index pattern templates // Index pattern template: alerts diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index 636ef63192..69f05e6336 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -1,82 +1,104 @@ import { Logger } from 'opensearch-dashboards/server'; +import { INITIALIZATION_TASK } from '../../../common/services/initialization/constants'; import { InitializationTaskDefinition, IInitializationService, InitializationTaskContext, } from './types'; import { addRoutes } from './routes'; -import { INITIALIZATION_TASK } from '../../../common/services/initialization/constants'; import { InitializationTask } from './lib/initialization-task'; export class InitializationService implements IInitializationService { - private items: Map; - private _coreStart: any; - constructor(private logger: Logger, private services: any) { + private readonly items: Map; + private coreStart: any; + + constructor( + private readonly logger: Logger, + private readonly services: any, + ) { this.items = new Map(); } + async setup({ core }) { this.logger.debug('Setup starts'); this.logger.debug('Adding routes'); + const router = core.http.createRouter(); + addRoutes(router, { initialization: this }); this.logger.debug('Added routes'); this.logger.debug('Setup finished'); } + async start({ core }) { this.logger.debug('Start starts'); - this._coreStart = core; + this.coreStart = core; await this.runAsInternal(); this.logger.debug('Start finished'); } + async stop() { this.logger.debug('Stop starts'); this.logger.debug('Stop finished'); } + register(task: InitializationTaskDefinition) { this.logger.debug(`Registering ${task.name}`); + if (this.items.has(task.name)) { throw new Error( `[${task.name}] was already registered. Ensure the name is unique or remove the duplicated registration of same task.`, ); } + this.items.set(task.name, new InitializationTask(task)); this.logger.debug(`Registered ${task.name}`); } + get(name: string) { this.logger.debug(`Getting task: [${name}]`); + if (!this.items.has(name)) { throw new Error(`Task [${name}] not found`); } + return this.items.get(name); } + getAll() { this.logger.debug('Getting all tasks'); - return Array.from(this.items.values()); + + return [...this.items.values()]; } + createRunContext(scope: InitializationTaskContext, context: any = {}) { return { ...this.services, ...context, scope }; } + async runAsInternal(taskNames?: string[]) { const ctx = this.createRunContext(INITIALIZATION_TASK.CONTEXT.INTERNAL, { - core: this._coreStart, + core: this.coreStart, }); + return await this.run(ctx, taskNames); } + createNewTaskFromRegisteredTask(name: string) { const task = this.get(name) as InitializationTask; + if (!task) { throw new Error(`Task [${name}] is not registered`); } + return new InitializationTask({ name, run: task._run }); } + private async run(ctx, taskNames?: string[]) { try { - if (this.items.size) { - const allTasks = Array.from(this.items.values()); + if (this.items.size > 0) { + const allTasks = [...this.items.values()]; const tasks = taskNames - ? allTasks.filter(({ name }) => - taskNames.some(taskName => taskName === name), - ) + ? allTasks.filter(({ name }) => taskNames.includes(name)) : allTasks; const results = await Promise.all( tasks.map(async item => { @@ -92,10 +114,12 @@ export class InitializationService implements IInitializationService { logger.error( `Error running task [${item.name}]: ${error.message}`, ); + return item.getInfo(); } }), ); + return results; } else { this.logger.info('No tasks'); diff --git a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts index a6c00c71fd..3d82b91c71 100644 --- a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts +++ b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts @@ -7,7 +7,8 @@ import { INITIALIZATION_TASK } from '../../../../common/services/initialization/ export class InitializationTask implements IInitializationTask { public name: string; - private _run: any; + // eslint-disable-next-line @typescript-eslint/naming-convention + private readonly _run: any; public status: InitializationTaskRunData['status'] = INITIALIZATION_TASK.RUN_STATUS.NOT_STARTED; public result: InitializationTaskRunData['result'] = @@ -19,10 +20,12 @@ export class InitializationTask implements IInitializationTask { public finishedAt: InitializationTaskRunData['finishedAt'] = null; public duration: InitializationTaskRunData['duration'] = null; public error = null; + constructor(task: InitializationTaskDefinition) { this.name = task.name; this._run = task.run; } + private init() { this.status = INITIALIZATION_TASK.RUN_STATUS.RUNNING; this.result = null; @@ -32,49 +35,53 @@ export class InitializationTask implements IInitializationTask { this.duration = null; this.error = null; } + async run(...params) { if (this.status === INITIALIZATION_TASK.RUN_STATUS.RUNNING) { throw new Error(`Another instance of task ${this.name} is running`); } + let error; + try { this.init(); this.data = await this._run(...params); this.result = INITIALIZATION_TASK.RUN_RESULT.SUCCESS; - } catch (e) { - error = e; + } catch (error_) { + error = error_; this.result = INITIALIZATION_TASK.RUN_RESULT.FAIL; - this.error = e.message; + this.error = error_.message; } finally { this.status = INITIALIZATION_TASK.RUN_STATUS.FINISHED; this.finishedAt = new Date().toISOString(); + + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const dateStartedAt = new Date(this.startedAt!); const dateFinishedAt = new Date(this.finishedAt); + this.duration = ((dateFinishedAt - dateStartedAt) as number) / 1000; } + if (error) { throw error; } + return this.getInfo(); } getInfo() { - return [ - 'name', - 'status', - 'result', - 'data', - 'createdAt', - 'startedAt', - 'finishedAt', - 'duration', - 'error', - ].reduce( - (accum, item) => ({ - ...accum, - [item]: this[item], - }), - {}, + return Object.fromEntries( + [ + 'name', + 'status', + 'result', + 'data', + 'createdAt', + 'startedAt', + 'finishedAt', + 'duration', + 'error', + ].map(item => [item, this[item]]), ) as IInitializationTask; } } diff --git a/plugins/wazuh-core/server/services/initialization/routes.ts b/plugins/wazuh-core/server/services/initialization/routes.ts index 568e0353a1..2be1b8905e 100644 --- a/plugins/wazuh-core/server/services/initialization/routes.ts +++ b/plugins/wazuh-core/server/services/initialization/routes.ts @@ -1,8 +1,32 @@ import { schema } from '@osd/config-schema'; -export function addRoutes(router, { initialization }) { - const getTaskList = (tasksAsString: string) => tasksAsString.split(','); +const getTaskList = (tasksAsString: string) => tasksAsString.split(','); + +interface EnhancedLoggerLog { + timestamp: string; + level: string; + message: string; +} + +function enhanceTaskLogger(logger) { + const logs: EnhancedLoggerLog[] = []; + const enhancedLogger = { + getLogs() { + return logs; + }, + }; + + for (const level of ['debug', 'info', 'warn', 'error']) { + enhancedLogger[level] = (message: string) => { + logs.push({ timestamp: new Date().toISOString(), level, message }); + logger[level](message); + }; + } + + return enhancedLogger; +} +export function addRoutes(router, { initialization }) { const validateTaskList = schema.maybe( schema.string({ validate(value: string) { @@ -11,14 +35,15 @@ export function addRoutes(router, { initialization }) { const invalidTasks = requestTasks.filter(requestTask => tasks.every(({ name }) => requestTask !== name), ); - if (invalidTasks.length) { + + if (invalidTasks.length > 0) { return `Invalid tasks: ${invalidTasks.join(', ')}`; } - return undefined; + + return; }, }), ); - const apiEndpointBase = '/api/initialization'; // Get the status of internal initialization tasks @@ -37,13 +62,14 @@ export function addRoutes(router, { initialization }) { ? getTaskList(request.query.tasks) : undefined; const logger = context.wazuh_core.logger; + logger.debug(`Getting initialization tasks related to internal scope`); + const tasks = tasksNames ? tasksNames.map(taskName => context.wazuh_core.initialization.get(taskName), ) : context.wazuh_core.initialization.getAll(); - const tasksData = tasks.map(task => task.getInfo()); logger.debug( @@ -60,10 +86,10 @@ export function addRoutes(router, { initialization }) { tasks: tasksData, }, }); - } catch (e) { + } catch (error) { return response.internalError({ body: { - message: `Error getting the internal initialization tasks: ${e.message}`, + message: `Error getting the internal initialization tasks: ${error.message}`, }, }); } @@ -89,9 +115,10 @@ export function addRoutes(router, { initialization }) { const logger = context.wazuh_core.logger; logger.debug(`Running initialization tasks related to internal scope`); - const results = await context.wazuh_core.initialization.runAsInternal( - tasksNames, - ); + + const results = + await context.wazuh_core.initialization.runAsInternal(tasksNames); + logger.info( `Initialization tasks related to internal scope were executed`, ); @@ -104,10 +131,10 @@ export function addRoutes(router, { initialization }) { tasks: results, }, }); - } catch (e) { + } catch (error) { return response.internalError({ body: { - message: `Error running the internal initialization tasks: ${e.message}`, + message: `Error running the internal initialization tasks: ${error.message}`, }, }); } @@ -132,11 +159,12 @@ export function addRoutes(router, { initialization }) { const logger = context.wazuh_core.logger; const username = ''; // TODO: get value const scope = 'user'; + logger.debug( `Getting initialization tasks related to user [${username}] scope [${scope}]`, ); - const initializationTasks = context.wazuh_core.initialization.get(); + const initializationTasks = context.wazuh_core.initialization.get(); const indexPatternTasks = initializationTasks .filter(({ name }) => name.startsWith('index-pattern:')) .map(({ name }) => @@ -151,12 +179,9 @@ export function addRoutes(router, { initialization }) { name, ), ); - const allUserTasks = [...indexPatternTasks, ...settingsTasks]; const tasks = tasksNames - ? allUserTasks.filter(({ name }) => - tasksNames.some(taskName => taskName === name), - ) + ? allUserTasks.filter(({ name }) => tasksNames.includes(name)) : allUserTasks; logger.debug( @@ -171,12 +196,13 @@ export function addRoutes(router, { initialization }) { ); logger.debug(`Running tasks for user [${username}] scope [${scope}]`); + const results = await Promise.all( tasks.map(async task => { const taskLogger = enhanceTaskLogger(logger); - let data; + try { - data = await task.run({ + await task.run({ ...taskContext, // TODO: use user selection index patterns logger: taskLogger, @@ -187,8 +213,10 @@ export function addRoutes(router, { initialization }) { } : {}), }); - } catch (e) { + } catch { + /* empty */ } finally { + // eslint-disable-next-line no-unsafe-finally return { logs: taskLogger.getLogs(), ...task.getInfo(), @@ -201,12 +229,11 @@ export function addRoutes(router, { initialization }) { const initialMessage = 'All the initialization tasks related to user scope were executed.'; - const message = [ initialMessage, results.some(({ error }) => error) && 'There was some errors.', ] - .filter(v => v) + .filter(Boolean) .join(' '); return response.ok({ @@ -215,28 +242,13 @@ export function addRoutes(router, { initialization }) { tasks: results, }, }); - } catch (e) { + } catch (error) { return response.internalError({ body: { - message: `Error initializating the tasks: ${e.message}`, + message: `Error initializating the tasks: ${error.message}`, }, }); } }, ); } - -function enhanceTaskLogger(logger) { - const logs = []; - - return ['debug', 'info', 'warn', 'error'].reduce( - (accum, level) => ({ - ...accum, - [level]: message => { - logs.push({ timestamp: new Date().toISOString(), level, message }); - logger[level].message; - }, - }), - { getLogs: () => logs }, - ); -} diff --git a/plugins/wazuh-core/server/services/initialization/types.ts b/plugins/wazuh-core/server/services/initialization/types.ts index 00eea6bb2b..254dae3af9 100644 --- a/plugins/wazuh-core/server/services/initialization/types.ts +++ b/plugins/wazuh-core/server/services/initialization/types.ts @@ -23,23 +23,23 @@ export interface InitializationTaskRunData { } export interface IInitializationTask extends InitializationTaskRunData { - run(ctx: Context): Promise; - getInfo(): InitializationTaskRunData; + run: (ctx: Context) => Promise; + getInfo: () => InitializationTaskRunData; } export type InitializationTaskContext = 'internal' | 'user'; export interface IInitializationService extends LifecycleService { - register(task: InitializationTaskDefinition): void; - get(taskName: string): InitializationTaskRunData; - getAll(): InitializationTaskRunData[]; - createRunContext( + register: (task: InitializationTaskDefinition) => void; + get: (taskName: string) => InitializationTaskRunData; + getAll: () => InitializationTaskRunData[]; + createRunContext: ( scope: InitializationTaskContext, context: ContextType, - ): { + ) => { scope: InitializationTaskContext; }; - runAsInternal(tasks?: string[]): Promise; + runAsInternal: (tasks?: string[]) => Promise; } export interface InitializationTaskRunContext extends WazuhCoreServices { diff --git a/plugins/wazuh-core/server/types.ts b/plugins/wazuh-core/server/types.ts index 998fd6f26a..d2e7bf16fe 100644 --- a/plugins/wazuh-core/server/types.ts +++ b/plugins/wazuh-core/server/types.ts @@ -23,8 +23,8 @@ export interface WazuhCorePluginStart extends WazuhCoreServices { }; } -export type PluginSetup = { - securityDashboards?: {}; // TODO: Add OpenSearch Dashboards Security interface -}; +export interface PluginSetup { + securityDashboards?: object; // TODO: Add OpenSearch Dashboards Security interface +} export * from './services/initialization/types'; From 97961cac71c98ddccd75983b1d9a708db010ece7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 2 Dec 2024 16:22:27 +0100 Subject: [PATCH 29/30] fix(initlization): lint --- .../services/initialization/constants.ts | 2 +- .../common/services/initialization/types.ts | 8 +-- .../server/initialization/index-patterns.ts | 3 +- .../server/initialization/server-api.ts | 15 ++--- .../server/initialization/templates.ts | 65 ++++++++++--------- plugins/wazuh-core/server/plugin.ts | 9 ++- .../services/initialization/initialization.ts | 6 +- .../initialization/lib/initialization-task.ts | 29 ++++----- 8 files changed, 67 insertions(+), 70 deletions(-) diff --git a/plugins/wazuh-core/common/services/initialization/constants.ts b/plugins/wazuh-core/common/services/initialization/constants.ts index 42f427a5ea..336fb7f41e 100644 --- a/plugins/wazuh-core/common/services/initialization/constants.ts +++ b/plugins/wazuh-core/common/services/initialization/constants.ts @@ -1,4 +1,4 @@ -export const INITIALIZATION_TASK = { +export const initializationTask = { RUN_STATUS: { NOT_STARTED: 'not_started', RUNNING: 'running', diff --git a/plugins/wazuh-core/common/services/initialization/types.ts b/plugins/wazuh-core/common/services/initialization/types.ts index 93894a003e..0118a181de 100644 --- a/plugins/wazuh-core/common/services/initialization/types.ts +++ b/plugins/wazuh-core/common/services/initialization/types.ts @@ -1,13 +1,13 @@ -import { INITIALIZATION_TASK } from './constants'; +import { initializationTask } from './constants'; -type RunStatusEnum = (typeof INITIALIZATION_TASK)['RUN_STATUS']; +type RunStatusEnum = (typeof initializationTask)['RUN_STATUS']; export type InitializationTaskRunStatus = RunStatusEnum[keyof RunStatusEnum]; -type RunResultEnum = (typeof INITIALIZATION_TASK)['RUN_RESULT']; +type RunResultEnum = (typeof initializationTask)['RUN_RESULT']; export type InitializationTaskRunResult = RunResultEnum[keyof RunResultEnum]; -type ContextEnum = (typeof INITIALIZATION_TASK)['CONTEXT']; +type ContextEnum = (typeof initializationTask)['CONTEXT']; export type InitializationTaskContext = ContextEnum[keyof ContextEnum]; diff --git a/plugins/wazuh-core/server/initialization/index-patterns.ts b/plugins/wazuh-core/server/initialization/index-patterns.ts index 42b4e73f57..a6af4b3e25 100644 --- a/plugins/wazuh-core/server/initialization/index-patterns.ts +++ b/plugins/wazuh-core/server/initialization/index-patterns.ts @@ -219,8 +219,7 @@ export const initializationTaskCreatorIndexPattern = ({ }: { getIndexPatternID: (ctx: any) => Promise; taskName: string; - // eslint-disable-next-line @typescript-eslint/no-empty-object-type - options: {}; + options: object; configurationSettingKey: string; }) => { return { diff --git a/plugins/wazuh-core/server/initialization/server-api.ts b/plugins/wazuh-core/server/initialization/server-api.ts index d6b15b868c..8b3dbb3fe0 100644 --- a/plugins/wazuh-core/server/initialization/server-api.ts +++ b/plugins/wazuh-core/server/initialization/server-api.ts @@ -68,15 +68,14 @@ export async function serverAPIConnectionCompatibility( ctx.logger.warn( `Error checking the connection and compatibility with server API [${apiHostID}]: ${error.message}`, ); - } finally { - // eslint-disable-next-line no-unsafe-finally - return { - connection, - compatibility, - api_version: apiVersion, - id: apiHostID, - }; } + + return { + connection, + compatibility, + api_version: apiVersion, + id: apiHostID, + }; } async function serversAPIConnectionCompatibility( diff --git a/plugins/wazuh-core/server/initialization/templates.ts b/plugins/wazuh-core/server/initialization/templates.ts index 2afb6d044f..6dd288250a 100644 --- a/plugins/wazuh-core/server/initialization/templates.ts +++ b/plugins/wazuh-core/server/initialization/templates.ts @@ -4,38 +4,39 @@ export function getTemplateForIndexPattern( indexPatternTitle: string, templates: { name: string; index_patterns: string }[], ) { - // eslint-disable-next-line @typescript-eslint/naming-convention - return templates.filter(({ index_patterns }: { index_patterns: string }) => { - const [, cleanIndexPatterns] = index_patterns.match(/\[(.+)]/) || [ - null, - null, - ]; - - if (!cleanIndexPatterns) { - return false; - } - - const indexPatterns = cleanIndexPatterns.match(/([^\s,]+)/g); - - if (!indexPatterns) { - return false; - } - - const lastChar = indexPatternTitle.at(-1); - const indexPatternTitleCleaned = - lastChar === '*' ? indexPatternTitle.slice(0, -1) : indexPatternTitle; - - return indexPatterns.some(indexPattern => { - const lastChar = indexPattern.at(-1); - const indexPatternCleaned = - lastChar === '*' ? indexPattern.slice(0, -1) : indexPattern; - - return ( - indexPatternCleaned.includes(indexPatternTitleCleaned) || - indexPatternTitleCleaned.includes(indexPatternCleaned) - ); - }); - }); + return templates.filter( + ({ index_patterns: indexPatternsTemplate }: { index_patterns: string }) => { + const [, cleanIndexPatterns] = indexPatternsTemplate.match(/\[(.+)]/) || [ + null, + null, + ]; + + if (!cleanIndexPatterns) { + return false; + } + + const indexPatterns = cleanIndexPatterns.match(/([^\s,]+)/g); + + if (!indexPatterns) { + return false; + } + + const lastChar = indexPatternTitle.at(-1); + const indexPatternTitleCleaned = + lastChar === '*' ? indexPatternTitle.slice(0, -1) : indexPatternTitle; + + return indexPatterns.some(indexPattern => { + const lastChar = indexPattern.at(-1); + const indexPatternCleaned = + lastChar === '*' ? indexPattern.slice(0, -1) : indexPattern; + + return ( + indexPatternCleaned.includes(indexPatternTitleCleaned) || + indexPatternTitleCleaned.includes(indexPatternCleaned) + ); + }); + }, + ); } export const checkIndexPatternHasTemplate = async ( diff --git a/plugins/wazuh-core/server/plugin.ts b/plugins/wazuh-core/server/plugin.ts index ea614c532b..cb1d53fcb2 100644 --- a/plugins/wazuh-core/server/plugin.ts +++ b/plugins/wazuh-core/server/plugin.ts @@ -49,13 +49,12 @@ export class WazuhCorePlugin { private readonly logger: Logger; private readonly services: Record; - // eslint-disable-next-line @typescript-eslint/naming-convention - private readonly _internal: Record; + private readonly internal: Record; constructor(private readonly initializerContext: PluginInitializerContext) { this.logger = initializerContext.logger.get(); this.services = {}; - this._internal = {}; + this.internal = {}; } public async setup( @@ -66,7 +65,7 @@ export class WazuhCorePlugin this.services.dashboardSecurity = createDashboardSecurity(plugins); - this._internal.configurationStore = new ConfigurationStore( + this.internal.configurationStore = new ConfigurationStore( this.logger.get('configuration-store'), { cache_seconds: WAZUH_CORE_CONFIGURATION_CACHE_SECONDS, @@ -75,7 +74,7 @@ export class WazuhCorePlugin ); this.services.configuration = new Configuration( this.logger.get('configuration'), - this._internal.configurationStore, + this.internal.configurationStore, ); // Enhance configuration service diff --git a/plugins/wazuh-core/server/services/initialization/initialization.ts b/plugins/wazuh-core/server/services/initialization/initialization.ts index 69f05e6336..f9df0d6471 100644 --- a/plugins/wazuh-core/server/services/initialization/initialization.ts +++ b/plugins/wazuh-core/server/services/initialization/initialization.ts @@ -1,5 +1,5 @@ import { Logger } from 'opensearch-dashboards/server'; -import { INITIALIZATION_TASK } from '../../../common/services/initialization/constants'; +import { initializationTask } from '../../../common/services/initialization/constants'; import { InitializationTaskDefinition, IInitializationService, @@ -76,7 +76,7 @@ export class InitializationService implements IInitializationService { } async runAsInternal(taskNames?: string[]) { - const ctx = this.createRunContext(INITIALIZATION_TASK.CONTEXT.INTERNAL, { + const ctx = this.createRunContext(initializationTask.CONTEXT.INTERNAL, { core: this.coreStart, }); @@ -90,7 +90,7 @@ export class InitializationService implements IInitializationService { throw new Error(`Task [${name}] is not registered`); } - return new InitializationTask({ name, run: task._run }); + return new InitializationTask({ name, run: task.runInternal }); } private async run(ctx, taskNames?: string[]) { diff --git a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts index 3d82b91c71..82e69c84e7 100644 --- a/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts +++ b/plugins/wazuh-core/server/services/initialization/lib/initialization-task.ts @@ -3,16 +3,15 @@ import { InitializationTaskRunData, IInitializationTask, } from '../types'; -import { INITIALIZATION_TASK } from '../../../../common/services/initialization/constants'; +import { initializationTask } from '../../../../common/services/initialization/constants'; export class InitializationTask implements IInitializationTask { public name: string; - // eslint-disable-next-line @typescript-eslint/naming-convention - private readonly _run: any; + private readonly runInternal: any; public status: InitializationTaskRunData['status'] = - INITIALIZATION_TASK.RUN_STATUS.NOT_STARTED; + initializationTask.RUN_STATUS.NOT_STARTED; public result: InitializationTaskRunData['result'] = - INITIALIZATION_TASK.RUN_RESULT.NULL; + initializationTask.RUN_RESULT.NULL; public data: any = null; public createdAt: InitializationTaskRunData['createdAt'] = new Date().toISOString(); @@ -23,11 +22,11 @@ export class InitializationTask implements IInitializationTask { constructor(task: InitializationTaskDefinition) { this.name = task.name; - this._run = task.run; + this.runInternal = task.run; } private init() { - this.status = INITIALIZATION_TASK.RUN_STATUS.RUNNING; + this.status = initializationTask.RUN_STATUS.RUNNING; this.result = null; this.data = null; this.startedAt = new Date().toISOString(); @@ -37,7 +36,7 @@ export class InitializationTask implements IInitializationTask { } async run(...params) { - if (this.status === INITIALIZATION_TASK.RUN_STATUS.RUNNING) { + if (this.status === initializationTask.RUN_STATUS.RUNNING) { throw new Error(`Another instance of task ${this.name} is running`); } @@ -45,21 +44,21 @@ export class InitializationTask implements IInitializationTask { try { this.init(); - this.data = await this._run(...params); - this.result = INITIALIZATION_TASK.RUN_RESULT.SUCCESS; + this.data = await this.runInternal(...params); + this.result = initializationTask.RUN_RESULT.SUCCESS; } catch (error_) { error = error_; - this.result = INITIALIZATION_TASK.RUN_RESULT.FAIL; + this.result = initializationTask.RUN_RESULT.FAIL; this.error = error_.message; } finally { - this.status = INITIALIZATION_TASK.RUN_STATUS.FINISHED; + this.status = initializationTask.RUN_STATUS.FINISHED; this.finishedAt = new Date().toISOString(); - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - const dateStartedAt = new Date(this.startedAt!); + const dateStartedAt = new Date(this.startedAt as string); const dateFinishedAt = new Date(this.finishedAt); - this.duration = ((dateFinishedAt - dateStartedAt) as number) / 1000; + this.duration = + ((dateFinishedAt.getTime() - dateStartedAt.getTime()) as number) / 1000; } if (error) { From c27446aa34d26c032f1c39ff319c66fe310b069f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antonio=20David=20Guti=C3=A9rrez?= Date: Mon, 2 Dec 2024 16:24:01 +0100 Subject: [PATCH 30/30] fix(test): service name --- plugins/wazuh-core/server/initialization/server-api.test.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/wazuh-core/server/initialization/server-api.test.ts b/plugins/wazuh-core/server/initialization/server-api.test.ts index cb1aec5090..60aaffc99e 100644 --- a/plugins/wazuh-core/server/initialization/server-api.test.ts +++ b/plugins/wazuh-core/server/initialization/server-api.test.ts @@ -5,7 +5,7 @@ import { import { webDocumentationLink } from '../../common/services/web_documentation'; import { version as appVersion } from '../../package.json'; import { - ServerAPIConnectionCompatibility, + serverAPIConnectionCompatibility, checkAppServerCompatibility, } from './server-api'; @@ -35,7 +35,7 @@ describe('checkAppServerCompatibility', () => { ); }); -describe('ServerAPIConnectionCompatibility', () => { +describe('serverAPIConnectionCompatibility', () => { it.each` apiHostID | apiVersionResponse | isCompatible ${'server1'} | ${{ api_version: '5.0.0' }} | ${true} @@ -46,7 +46,7 @@ describe('ServerAPIConnectionCompatibility', () => { async ({ apiHostID, apiVersionResponse, isCompatible }) => { const loggerMock = jest.fn(); - await ServerAPIConnectionCompatibility( + await serverAPIConnectionCompatibility( { manageHosts: { get: () => hosts,