From 1cb24f1b0ccb6c77f3c300648ee2b1f6e9c4b660 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 13:39:57 -0300 Subject: [PATCH 01/33] Refactor error response function and message handling --- plugins/main/server/lib/error-response.ts | 44 ++++++++++++++--------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/plugins/main/server/lib/error-response.ts b/plugins/main/server/lib/error-response.ts index 7118e3e209..bc97232cb2 100644 --- a/plugins/main/server/lib/error-response.ts +++ b/plugins/main/server/lib/error-response.ts @@ -20,13 +20,18 @@ */ /** * Returns a suitable error message - * @param {String} message Error message - * @param {Number} code Error code - * @param {Number} statusCode Error status code + * @param {string} message Error message + * @param {number} code Error code + * @param {number} statusCode Error status code * @returns {Object} Error response object */ -export function ErrorResponse(message = null, code = null, statusCode = null, response) { - message.includes('password: ') +export function ErrorResponse( + message: string | null = '', + code: number | null = null, + statusCode: number | null = null, + response: object, +) { + message?.includes('password: ') ? (message = message.split('password: ')[0] + ' password: ***') : false; let filteredMessage = ''; @@ -36,23 +41,30 @@ export function ErrorResponse(message = null, code = null, statusCode = null, re filteredMessage = 'Wrong protocol being used to connect to the API'; } else if ( isString && - (message.includes('ENOTFOUND') || - message.includes('EHOSTUNREACH') || - message.includes('EINVAL') || - message.includes('EAI_AGAIN')) && + (message?.includes('ENOTFOUND') || + message?.includes('EHOSTUNREACH') || + message?.includes('EINVAL') || + message?.includes('EAI_AGAIN')) && code === 3005 ) { filteredMessage = 'API is not reachable. Please check your url and port.'; - } else if (isString && message.includes('ECONNREFUSED') && code === 3005) { + } else if (isString && message?.includes('ECONNREFUSED') && code === 3005) { filteredMessage = 'API is not reachable. Please check your url and port.'; - } else if (isString && message.toLowerCase().includes('not found') && code === 3002) { - filteredMessage = 'It seems the selected API was deleted.'; } else if ( isString && - message.includes('ENOENT') && - message.toLowerCase().includes('no such file or directory') && - message.toLowerCase().includes('data') && - code === 5029 || code === 5030 || code === 5031 || code === 5032 + message?.toLowerCase().includes('not found') && + code === 3002 + ) { + filteredMessage = 'It seems the selected API was deleted.'; + } else if ( + (isString && + message?.includes('ENOENT') && + message?.toLowerCase().includes('no such file or directory') && + message?.toLowerCase().includes('data') && + code === 5029) || + code === 5030 || + code === 5031 || + code === 5032 ) { filteredMessage = 'Reporting was aborted - no such file or directory'; } else if (isString && code === 5029) { From bf5b7112da7c135e69fff41a2f65751d12e6d786 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 13:40:10 -0300 Subject: [PATCH 02/33] Refactor code for fetching manager info in wazuh-api --- plugins/main/server/controllers/wazuh-api.ts | 82 +++++++++++--------- 1 file changed, 47 insertions(+), 35 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 545e989e85..74762c893e 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -107,6 +107,20 @@ export class WazuhApiCtrl { } } + private async requestManagerInfo( + context: RequestHandlerContext, + id: string, + { forceRefresh }: { forceRefresh?: boolean } = {}, + ) { + // Fetch needed information about the cluster and the manager itself + return await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/manager/info`, + {}, + { apiHostID: id, forceRefresh }, + ); + } + /** * Returns if the wazuh-api configuration is working * @param {Object} context @@ -133,37 +147,38 @@ export class WazuhApiCtrl { context.wazuh.logger.debug(`${id} exists`); - // Fetch needed information about the cluster and the manager itself - const responseManagerInfo = - await context.wazuh.api.client.asInternalUser.request( - 'get', - `/manager/info`, - {}, - { apiHostID: id, forceRefresh: true }, - ); + const promises = [ + this.requestManagerInfo(context, id, { + forceRefresh: true, + }), + context.wazuh_core.manageHosts.getRegistryDataByHost(apiHostData, { + throwError: true, + }), + ]; - // Look for socket-related errors - if (this.checkResponseIsDown(context, responseManagerInfo)) { - return ErrorResponse( - `ERROR3099 - ${ - responseManagerInfo.data.detail || 'Server not ready yet' - }`, - 3099, - HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, - response, - ); - } + const settledResult = await Promise.allSettled(promises); + let responseManagerInfo; - // If we have a valid response from the Wazuh API - try { - const { status, manager, node, cluster } = - await context.wazuh_core.manageHosts.getRegistryDataByHost( - apiHostData, - { - throwError: true, - }, + if (settledResult[0].status === 'fulfilled') { + responseManagerInfo = settledResult[0].value; + // Look for socket-related errors + if (this.checkResponseIsDown(context, responseManagerInfo)) { + return ErrorResponse( + `ERROR3099 - ${ + responseManagerInfo.data.detail || 'Server not ready yet' + }`, + 3099, + HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, + response, ); + } + } else { + throw new Error(settledResult[0].reason); + } + // If we have a valid response from the Wazuh API + if (settledResult[1].status === 'fulfilled') { + const { status, manager, node, cluster } = settledResult[1].value; api.cluster_info = { status, manager, node, cluster }; return response.ok({ @@ -173,7 +188,7 @@ export class WazuhApiCtrl { idChanged: request.body.idChanged || null, }, }); - } catch (error) { + } else { // If we have an invalid response from the Wazuh API throw new Error( responseManagerInfo.data.detail || @@ -202,13 +217,10 @@ export class WazuhApiCtrl { try { const { id } = api; - const responseManagerInfo = - await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/manager/info`, - {}, - { apiHostID: id }, - ); + const responseManagerInfo = await this.requestManagerInfo( + context, + id, + ); if (this.checkResponseIsDown(context, responseManagerInfo)) { return ErrorResponse( From 0fe0f44b1f3f170ba78a18b3a599c57bd8c900af Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 14:07:22 -0300 Subject: [PATCH 03/33] Fix loading speed issue (#7099) --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a08c5e23c0..7c825d8f53 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed security policy exception when it contained deprecated actions [#7042](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7042) - Fixed export formatted csv data with special characters from tables [#7048](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7048) - Fixed column reordering feature [#7072](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7072) +- Fixed loading speed [#7099](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7099) ### Removed From a71486b8ba6bd53228486e06c56b8d4ee0306bd4 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:00:42 -0300 Subject: [PATCH 04/33] Add WAZUH_ERROR_DAEMONS_NOT_READY constant to error messages --- .../components/health-check/services/check-api.service.ts | 7 ++++++- .../components/management/configuration/utils/wz-fetch.js | 4 ++-- plugins/main/public/react-services/error-handler.ts | 3 ++- plugins/main/server/controllers/wazuh-api.ts | 7 +++++-- 4 files changed, 15 insertions(+), 6 deletions(-) diff --git a/plugins/main/public/components/health-check/services/check-api.service.ts b/plugins/main/public/components/health-check/services/check-api.service.ts index dbbb5d44b7..9b8fcbcb86 100644 --- a/plugins/main/public/components/health-check/services/check-api.service.ts +++ b/plugins/main/public/components/health-check/services/check-api.service.ts @@ -18,6 +18,7 @@ import { CheckLogger } from '../types/check_logger'; import { PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, PLUGIN_APP_NAME, + WAZUH_ERROR_DAEMONS_NOT_READY, } from '../../../../common/constants'; import { webDocumentationLink } from '../../../../common/services/web_documentation'; @@ -52,7 +53,11 @@ const trySetDefault = async (checkLogger: CheckLogger) => { } if (errors.length) { for (var j = 0; j < errors.length; j++) { - if (errors[j].includes('ERROR3099 - 405: Method Not Allowed')) { + if ( + errors[j].includes( + `${WAZUH_ERROR_DAEMONS_NOT_READY} - 405: Method Not Allowed`, + ) + ) { return Promise.reject( `No API available to connect. This may be related to a version mismatch between server and ${PLUGIN_APP_NAME}. Please check the versions and try again. Read more about this in our troubleshooting guide: ${webDocumentationLink( PLUGIN_PLATFORM_WAZUH_DOCUMENTATION_URL_PATH_TROUBLESHOOTING, diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 66db0df048..848a7915c5 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -14,7 +14,7 @@ import { WzRequest } from '../../../../../../react-services/wz-request'; import { replaceIllegalXML } from './xml'; import { getToasts } from '../../../../../../kibana-services'; import { delayAsPromise } from '../../../../../../../common/utils'; -import { AGENT_SYNCED_STATUS } from '../../../../../../../common/constants'; +import { AGENT_SYNCED_STATUS, WAZUH_ERROR_DAEMONS_NOT_READY } from '../../../../../../../common/constants'; /** * Get configuration for an agent/manager of request sections @@ -144,7 +144,7 @@ export const handleError = async ( const message = extractMessage(error); const messageIsString = typeof message === 'string'; try { - if (messageIsString && message.includes('ERROR3099')) { + if (messageIsString && message.includes(WAZUH_ERROR_DAEMONS_NOT_READY)) { updateWazuhNotReadyYet('Server not ready yet.'); await makePing(updateWazuhNotReadyYet, isCluster); return; diff --git a/plugins/main/public/react-services/error-handler.ts b/plugins/main/public/react-services/error-handler.ts index 3bf1e5bb52..a7d71f8b2a 100644 --- a/plugins/main/public/react-services/error-handler.ts +++ b/plugins/main/public/react-services/error-handler.ts @@ -14,6 +14,7 @@ import store from '../redux/store'; import { updateWazuhNotReadyYet } from '../redux/actions/appStateActions'; import { WzMisc } from '../factories/misc'; import { CheckDaemonsStatus } from './check-daemons-status'; +import { WAZUH_ERROR_DAEMONS_NOT_READY } from '../../common/constants'; interface IHistoryItem { text: string; @@ -142,7 +143,7 @@ export class ErrorHandler { static handle(error, location, params = { warning: false, silent: false }) { const message = ErrorHandler.extractMessage(error); const messageIsString = typeof message === 'string'; - if (messageIsString && message.includes('ERROR3099')) { + if (messageIsString && message.includes(WAZUH_ERROR_DAEMONS_NOT_READY)) { const updateNotReadyYet = updateWazuhNotReadyYet('Server not ready yet.'); store.dispatch(updateNotReadyYet); CheckDaemonsStatus.makePing().catch(error => {}); diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 74762c893e..e0ab3c02f2 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -16,7 +16,10 @@ import { Parser } from 'json2csv'; import { KeyEquivalence } from '../../common/csv-key-equivalence'; import { ApiErrorEquivalence } from '../lib/api-errors-equivalence'; import apiRequestList from '../../common/api-info/endpoints'; -import { HTTP_STATUS_CODES } from '../../common/constants'; +import { + HTTP_STATUS_CODES, + WAZUH_ERROR_DAEMONS_NOT_READY, +} from '../../common/constants'; import { addJobToQueue } from '../start/queue'; import jwtDecode from 'jwt-decode'; import { @@ -164,7 +167,7 @@ export class WazuhApiCtrl { // Look for socket-related errors if (this.checkResponseIsDown(context, responseManagerInfo)) { return ErrorResponse( - `ERROR3099 - ${ + `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ responseManagerInfo.data.detail || 'Server not ready yet' }`, 3099, From fcd00242c1ff0aad040b16523fd71f3ddd289538 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:03:23 -0300 Subject: [PATCH 05/33] Add ERROR_CODES enum for error handling --- plugins/main/common/constants.ts | 5 +++++ plugins/main/server/controllers/wazuh-api.ts | 9 +++++---- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 40ef55817b..8ec19b6eb3 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -527,3 +527,8 @@ export const SEARCH_BAR_DEBOUNCE_UPDATE_TIME = 400; // ID used to refer the createOsdUrlStateStorage state export const OSD_URL_STATE_STORAGE_ID = 'state:storeInSessionStorage'; + +export enum ERROR_CODES { + EPROTO = 'EPROTO', + ECONNREFUSED = 'ECONNREFUSED', +}; diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index e0ab3c02f2..74d763898c 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -17,6 +17,7 @@ import { KeyEquivalence } from '../../common/csv-key-equivalence'; import { ApiErrorEquivalence } from '../lib/api-errors-equivalence'; import apiRequestList from '../../common/api-info/endpoints'; import { + ERROR_CODES, HTTP_STATUS_CODES, WAZUH_ERROR_DAEMONS_NOT_READY, } from '../../common/constants'; @@ -199,14 +200,14 @@ export class WazuhApiCtrl { ); } } catch (error) { - if (error.code === 'EPROTO') { + if (error.code === ERROR_CODES.EPROTO) { return response.ok({ body: { statusCode: HTTP_STATUS_CODES.OK, data: { apiIsDown: true }, }, }); - } else if (error.code === 'ECONNREFUSED') { + } else if (error.code === ERROR_CODES.ECONNREFUSED) { return response.ok({ body: { statusCode: HTTP_STATUS_CODES.OK, @@ -385,7 +386,7 @@ export class WazuhApiCtrl { response, ); } - if (error.code === 'EPROTO') { + if (error.code === ERROR_CODES.EPROTO) { return ErrorResponse( 'Wrong protocol being used to connect to the API', 3005, @@ -578,7 +579,7 @@ export class WazuhApiCtrl { const check = await this.checkDaemons(context, api, path); return check; } catch (error) { - const isDown = (error || {}).code === 'ECONNREFUSED'; + const isDown = error?.code === ERROR_CODES.ECONNREFUSED; if (!isDown) { context.wazuh.logger.error( 'Server API is online but the server is not ready yet', From 654ff15575442f9d57a25182cb0f89374b1148c6 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:03:36 -0300 Subject: [PATCH 06/33] Refactor API routes to use controller functions directly --- plugins/main/server/routes/wazuh-api.ts | 26 +++++++++---------------- 1 file changed, 9 insertions(+), 17 deletions(-) diff --git a/plugins/main/server/routes/wazuh-api.ts b/plugins/main/server/routes/wazuh-api.ts index 9e0e2cc1bd..c44b16a3c5 100644 --- a/plugins/main/server/routes/wazuh-api.ts +++ b/plugins/main/server/routes/wazuh-api.ts @@ -16,8 +16,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => - ctrl.checkStoredAPI(context, request, response), + ctrl.checkStoredAPI, ); // Check if credentials on POST connect to Wazuh API. Not storing them! @@ -44,8 +43,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => - ctrl.checkAPI(context, request, response), + ctrl.checkAPI, ); router.post( @@ -58,8 +56,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => - ctrl.getToken(context, request, response), + ctrl.getToken, ); // Returns the request result (With error control) @@ -75,8 +72,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => - ctrl.requestApi(context, request, response), + ctrl.requestApi, ); // Returns data from the Wazuh API on CSV readable format @@ -91,7 +87,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => ctrl.csv(context, request, response), + ctrl.csv, ); // Returns a route list used by the Dev Tools @@ -100,8 +96,7 @@ export function WazuhApiRoutes(router: IRouter) { path: '/api/routes', validate: false, }, - async (context, request, response) => - ctrl.getRequestList(context, request, response), + ctrl.getRequestList, ); // Return Wazuh Appsetup info @@ -110,8 +105,7 @@ export function WazuhApiRoutes(router: IRouter) { path: '/api/setup', validate: false, }, - async (context, request, response) => - ctrl.getSetupInfo(context, request, response), + ctrl.getSetupInfo, ); // Return basic information of syscollector for given agent @@ -124,8 +118,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - async (context, request, response) => - ctrl.getSyscollector(context, request, response), + ctrl.getSyscollector, ); // Return app logos configuration @@ -135,7 +128,6 @@ export function WazuhApiRoutes(router: IRouter) { validate: false, options: { authRequired: false }, }, - async (context, request, response) => - ctrl.getAppLogos(context, request, response), + ctrl.getAppLogos, ); } From f1b4e4654054d417afa36a2b84cc2e625de310b7 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:03:48 -0300 Subject: [PATCH 07/33] Refactor getCookieValueByName to handle undefined input --- plugins/main/server/lib/cookie.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/main/server/lib/cookie.ts b/plugins/main/server/lib/cookie.ts index b429a27066..670a16a7cf 100644 --- a/plugins/main/server/lib/cookie.ts +++ b/plugins/main/server/lib/cookie.ts @@ -10,9 +10,12 @@ * Find more information about this on the LICENSE file. */ -export const getCookieValueByName = (cookie: string, name: string): (string | undefined) => { +export const getCookieValueByName = ( + cookie: string | undefined, + name: string, +): string | undefined => { if (!cookie) return; const cookieRegExp = new RegExp(`.*${name}=([^;]+)`); const [_, cookieNameValue] = cookie.match(cookieRegExp) || []; return cookieNameValue; -} \ No newline at end of file +}; From d9c7281f52a982278ecd5212a4b0596bf9751622 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:04:22 -0300 Subject: [PATCH 08/33] Update code to handle string error codes in ErrorResponse function --- plugins/main/server/lib/error-response.ts | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/plugins/main/server/lib/error-response.ts b/plugins/main/server/lib/error-response.ts index bc97232cb2..219047944a 100644 --- a/plugins/main/server/lib/error-response.ts +++ b/plugins/main/server/lib/error-response.ts @@ -10,6 +10,8 @@ * Find more information about this on the LICENSE file. */ +import { ERROR_CODES } from '../../common/constants'; + /** * Error codes: * wazuh-api-elastic 20XX @@ -27,7 +29,7 @@ */ export function ErrorResponse( message: string | null = '', - code: number | null = null, + code: string | number | null = null, statusCode: number | null = null, response: object, ) { @@ -48,7 +50,11 @@ export function ErrorResponse( code === 3005 ) { filteredMessage = 'API is not reachable. Please check your url and port.'; - } else if (isString && message?.includes('ECONNREFUSED') && code === 3005) { + } else if ( + isString && + message?.includes(ERROR_CODES.ECONNREFUSED) && + code === 3005 + ) { filteredMessage = 'API is not reachable. Please check your url and port.'; } else if ( isString && From 5b81eb87849d58753e346c88daf576ebb01b9088 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:04:35 -0300 Subject: [PATCH 09/33] Update queue job run function to handle context error --- plugins/main/server/start/queue/index.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/main/server/start/queue/index.ts b/plugins/main/server/start/queue/index.ts index 707ef2469a..c24fc5b639 100644 --- a/plugins/main/server/start/queue/index.ts +++ b/plugins/main/server/start/queue/index.ts @@ -12,13 +12,13 @@ import cron from 'node-cron'; import { WAZUH_QUEUE_CRON_FREQ } from '../../../common/constants'; -export let queue = []; +export let queue: IQueueJob[] = []; export interface IQueueJob { /** Date object to start the job */ startAt: Date; /** Function to execute */ - run: () => void; + run: (contextJob: any) => Promise; } /** @@ -62,7 +62,7 @@ export function jobQueueRun(context) { try { await executePendingJobs(context); } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); } }); } From 310856da2ce0ecb0d37ea7be6ebe0b261c6ecc35 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:04:48 -0300 Subject: [PATCH 10/33] Update parameter type in getCookieValueByName function --- plugins/wazuh-core/server/services/cookie.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/wazuh-core/server/services/cookie.ts b/plugins/wazuh-core/server/services/cookie.ts index 3d3beff12a..670a16a7cf 100644 --- a/plugins/wazuh-core/server/services/cookie.ts +++ b/plugins/wazuh-core/server/services/cookie.ts @@ -11,7 +11,7 @@ */ export const getCookieValueByName = ( - cookie: string, + cookie: string | undefined, name: string, ): string | undefined => { if (!cookie) return; From 4ab0edfdf262b37b3768f24f58f4c89ea3f87623 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:07:17 -0300 Subject: [PATCH 11/33] Add error handling for missing API parameters --- plugins/main/server/controllers/wazuh-api.ts | 42 +++++++++++--------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 74d763898c..91c1cce275 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -35,6 +35,12 @@ import { } from '../../package.json'; export class WazuhApiCtrl { + private readonly SERVER_API_PENDING_INITIALIZATION = + 'Server API is online but the server is not ready yet'; + private readonly SERVER_NOT_READY_YET = 'Server not ready yet'; + + private readonly MISSING_PARAM_API = 'Missing param: API'; + constructor() {} async getToken( @@ -169,7 +175,7 @@ export class WazuhApiCtrl { if (this.checkResponseIsDown(context, responseManagerInfo)) { return ErrorResponse( `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ - responseManagerInfo.data.detail || 'Server not ready yet' + responseManagerInfo.data.detail || this.SERVER_NOT_READY_YET }`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, @@ -228,8 +234,8 @@ export class WazuhApiCtrl { if (this.checkResponseIsDown(context, responseManagerInfo)) { return ErrorResponse( - `ERROR3099 - ${ - response.data.detail || 'Server not ready yet' + `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ + response.data.detail || this.SERVER_NOT_READY_YET }`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, @@ -269,19 +275,19 @@ export class WazuhApiCtrl { */ validateCheckApiParams(body) { if (!('username' in body)) { - return 'Missing param: API USERNAME'; + return this.MISSING_PARAM_API + ' USERNAME'; } if (!('password' in body) && !('id' in body)) { - return 'Missing param: API PASSWORD'; + return this.MISSING_PARAM_API + ' PASSWORD'; } if (!('url' in body)) { - return 'Missing param: API URL'; + return this.MISSING_PARAM_API + ' URL'; } if (!('port' in body)) { - return 'Missing param: API PORT'; + return this.MISSING_PARAM_API + ' PORT'; } if (!body.url.includes('https://') && !body.url.includes('http://')) { @@ -339,8 +345,8 @@ export class WazuhApiCtrl { ); } catch (error) { return ErrorResponse( - `ERROR3099 - ${ - error.response?.data?.detail || 'Server not ready yet' + `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ + error.response?.data?.detail || this.SERVER_NOT_READY_YET }`, 3099, error?.response?.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, @@ -411,9 +417,7 @@ export class WazuhApiCtrl { const isDown = socketErrorCodes.includes(status); isDown && - context.wazuh.logger.error( - 'Server API is online but the server is not ready yet', - ); + context.wazuh.logger.error(this.SERVER_API_PENDING_INITIALIZATION); return isDown; } @@ -460,7 +464,7 @@ export class WazuhApiCtrl { } if (!isValid) { - throw new Error('Server not ready yet'); + throw new Error(this.SERVER_NOT_READY_YET); } } catch (error) { context.wazuh.logger.error(error.message || error); @@ -581,11 +585,11 @@ export class WazuhApiCtrl { } catch (error) { const isDown = error?.code === ERROR_CODES.ECONNREFUSED; if (!isDown) { - context.wazuh.logger.error( - 'Server API is online but the server is not ready yet', - ); + context.wazuh.logger.error(this.SERVER_API_PENDING_INITIALIZATION); return ErrorResponse( - `ERROR3099 - ${error.message || 'Server not ready yet'}`, + `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ + (error as Error).message || this.SERVER_NOT_READY_YET + }`, 3099, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -606,7 +610,9 @@ export class WazuhApiCtrl { const responseIsDown = this.checkResponseIsDown(context, responseToken); if (responseIsDown) { return ErrorResponse( - `ERROR3099 - ${response.body.message || 'Server not ready yet'}`, + `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ + response.body.message || this.SERVER_NOT_READY_YET + }`, 3099, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, From 8502812b6de29ddf297c98af108f0bd2ae4ab436 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:10:02 -0300 Subject: [PATCH 12/33] Refactor error handling for consistency and readability --- plugins/main/server/controllers/wazuh-api.ts | 83 +++++++++----------- 1 file changed, 36 insertions(+), 47 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 91c1cce275..5d18476ff7 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -79,7 +79,9 @@ export class WazuhApiCtrl { } } catch (error) { context.wazuh.logger.error( - `Error decoding the API host entry token: ${error.message}`, + `Error decoding the API host entry token: ${ + (error as Error).message + }`, ); } } @@ -105,7 +107,7 @@ export class WazuhApiCtrl { }); } catch (error) { const errorMessage = `Error getting the authorization token: ${ - ((error.response || {}).data || {}).detail || error.message || error + error.response?.data?.detail || (error as Error).message || error }`; context.wazuh.logger.error(errorMessage); return ErrorResponse( @@ -250,17 +252,17 @@ export class WazuhApiCtrl { } catch (error) {} // eslint-disable-line } } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( - error.message || error, + (error as Error).message || error, 3020, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, ); } - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( - error.message || error, + (error as Error).message || error, 3002, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -365,7 +367,7 @@ export class WazuhApiCtrl { }); } } catch (error) { - context.wazuh.logger.warn(error.message || error); + context.wazuh.logger.warn((error as Error).message || error); if ( error && @@ -401,7 +403,7 @@ export class WazuhApiCtrl { ); } return ErrorResponse( - error.message || error, + (error as Error).message || error, 3005, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -413,7 +415,7 @@ export class WazuhApiCtrl { if (response.status !== HTTP_STATUS_CODES.OK) { // Avoid "Error communicating with socket" like errors const socketErrorCodes = [1013, 1014, 1017, 1018, 1019]; - const status = (response.data || {}).status || 1; + const status = response.data?.status || 1; const isDown = socketErrorCodes.includes(status); isDown && @@ -439,12 +441,10 @@ export class WazuhApiCtrl { { apiHostID: api.id }, ); - const daemons = - ((((response || {}).data || {}).data || {}).affected_items || [])[0] || - {}; + const daemons = response?.data?.data?.affected_items?.[0] || {}; const isCluster = - ((api || {}).cluster_info || {}).status === 'enabled' && + api?.cluster_info?.status === 'enabled' && typeof daemons['wazuh-clusterd'] !== 'undefined'; const wazuhdbExists = typeof daemons['wazuh-db'] !== 'undefined'; @@ -467,7 +467,7 @@ export class WazuhApiCtrl { throw new Error(this.SERVER_NOT_READY_YET); } } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return Promise.reject(error); } } @@ -488,8 +488,7 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} API response or ErrorResponse */ - async makeRequest(context, method, path, data, id, response) { - const devTools = !!(data || {}).devTools; + const devTools = !!data?.devTools; try { let api; try { @@ -524,30 +523,21 @@ export class WazuhApiCtrl { }; // Set content type application/xml if needed - if ( - typeof (data || {}).body === 'string' && - (data || {}).origin === 'xmleditor' - ) { + if (typeof data?.body === 'string' && data?.origin === 'xmleditor') { data.headers['content-type'] = 'application/xml'; delete data.origin; } - if ( - typeof (data || {}).body === 'string' && - (data || {}).origin === 'json' - ) { + if (typeof data?.body === 'string' && data?.origin === 'json') { data.headers['content-type'] = 'application/json'; delete data.origin; } - if ( - typeof (data || {}).body === 'string' && - (data || {}).origin === 'raw' - ) { + if (typeof data?.body === 'string' && data?.origin === 'raw') { data.headers['content-type'] = 'application/octet-stream'; delete data.origin; } - const delay = (data || {}).delay || 0; + const delay = data?.delay || 0; if (delay) { // Remove the delay parameter that is used to add the sever API request to the queue job. // This assumes the delay parameter is not used as part of the server API request. If it @@ -567,7 +557,7 @@ export class WazuhApiCtrl { } catch (error) { contextJob.wazuh.logger.error( `An error ocurred in the delayed request: "${method} ${path}": ${ - error.message || error + (error as Error).message || error }`, ); } @@ -618,7 +608,7 @@ export class WazuhApiCtrl { response, ); } - let responseBody = (responseToken || {}).data || {}; + let responseBody = responseToken?.data || {}; if (!responseBody) { responseBody = typeof responseBody === 'string' && @@ -652,21 +642,21 @@ export class WazuhApiCtrl { error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED ) { return ErrorResponse( - error.message || error, + (error as Error).message || error, error.code ? `API error: ${error.code}` : 3013, HTTP_STATUS_CODES.UNAUTHORIZED, response, ); } - const errorMsg = (error.response || {}).data || error.message; + const errorMsg = error.response?.data || (error as Error).message; context.wazuh.logger.error(errorMsg || error); if (devTools) { return response.ok({ body: { error: '3013', message: errorMsg || error }, }); } else { - if ((error || {}).code && ApiErrorEquivalence[error.code]) { - error.message = ApiErrorEquivalence[error.code]; + if (error?.code && ApiErrorEquivalence[error.code]) { + (error as Error).message = ApiErrorEquivalence[error.code]; } return ErrorResponse( errorMsg.detail || error, @@ -761,7 +751,7 @@ export class WazuhApiCtrl { throw new Error('Field path is required'); if (!request.body.id) throw new Error('Field id is required'); - const filters = Array.isArray(((request || {}).body || {}).filters) + const filters = Array.isArray(request?.body?.filters) ? request.body.filters : []; @@ -799,8 +789,7 @@ export class WazuhApiCtrl { request.body.filters.length && request.body.filters.find(filter => filter._isCDBList); - const totalItems = (((output || {}).data || {}).data || {}) - .total_affected_items; + const totalItems = output?.data?.data?.total_affected_items; if (totalItems && !isList) { params.offset = 0; @@ -906,9 +895,9 @@ export class WazuhApiCtrl { ); } } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( - error.message || error, + (error as Error).message || error, 3034, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -952,10 +941,10 @@ export class WazuhApiCtrl { }, }); } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( `Could not get data from wazuh-version registry due to ${ - error.message || error + (error as Error).message || error }`, 4005, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, @@ -999,7 +988,7 @@ export class WazuhApiCtrl { ), ]); - const result = data.map(item => (item.data || {}).data || []); + const result = data.map(item => item.data?.data || []); const [hardwareResponse, osResponse] = result; // Fill syscollector object @@ -1019,9 +1008,9 @@ export class WazuhApiCtrl { body: syscollector, }); } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( - error.message || error, + (error as Error).message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -1059,9 +1048,9 @@ export class WazuhApiCtrl { body: { logos }, }); } catch (error) { - context.wazuh.logger.error(error.message || error); + context.wazuh.logger.error((error as Error).message || error); return ErrorResponse( - error.message || error, + (error as Error).message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, From 91f253a1b53b80911cb46acfd430b4254dbe4389 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Tue, 15 Oct 2024 17:18:45 -0300 Subject: [PATCH 13/33] Update Wazuh API controller methods and parameters --- plugins/main/server/controllers/wazuh-api.ts | 43 ++++++++++++++++---- 1 file changed, 34 insertions(+), 9 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 5d18476ff7..5293dce6a6 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -59,7 +59,7 @@ export class WazuhApiCtrl { request.headers.cookie && username === decodeURIComponent( - getCookieValueByName(request.headers.cookie, 'wz-user'), + getCookieValueByName(request.headers.cookie, 'wz-user') ?? '', ) && idHost === getCookieValueByName(request.headers.cookie, 'wz-api') ) { @@ -275,7 +275,13 @@ export class WazuhApiCtrl { * This perfoms a validation of API params * @param {Object} body API params */ - validateCheckApiParams(body) { + validateCheckApiParams(body: { + username?: string; + password?: string; + url?: string; + port?: number; + id?: string; + }) { if (!('username' in body)) { return this.MISSING_PARAM_API + ' USERNAME'; } @@ -292,7 +298,7 @@ export class WazuhApiCtrl { return this.MISSING_PARAM_API + ' PORT'; } - if (!body.url.includes('https://') && !body.url.includes('http://')) { + if (!body.url?.includes('https://') && !body.url?.includes('http://')) { return 'protocol_error'; } @@ -332,7 +338,9 @@ export class WazuhApiCtrl { response, ); } - const options = { apiHostID: request.body.id }; + const options: { apiHostID: string; forceRefresh?: boolean } = { + apiHostID: request.body.id, + }; if (request.body.forceRefresh) { options['forceRefresh'] = request.body.forceRefresh; } @@ -411,7 +419,10 @@ export class WazuhApiCtrl { } } - checkResponseIsDown(context, response) { + checkResponseIsDown( + context: RequestHandlerContext, + response: { status: number; data?: { status: number } }, + ) { if (response.status !== HTTP_STATUS_CODES.OK) { // Avoid "Error communicating with socket" like errors const socketErrorCodes = [1013, 1014, 1017, 1018, 1019]; @@ -428,11 +439,11 @@ export class WazuhApiCtrl { /** * Check main Wazuh daemons status - * @param {*} context Endpoint context + * @param {RequestHandlerContext} context Endpoint context * @param {*} api API entry stored in .wazuh - * @param {*} path Optional. Wazuh API target path. + * @param {string} path Optional. Wazuh API target path. */ - async checkDaemons(context, api, path) { + async checkDaemons(context: RequestHandlerContext, api, path: string) { try { const response = await context.wazuh.api.client.asInternalUser.request( 'GET', @@ -472,7 +483,7 @@ export class WazuhApiCtrl { } } - sleep(timeMs) { + sleep(timeMs: number) { // eslint-disable-next-line return new Promise((resolve, reject) => { setTimeout(resolve, timeMs); @@ -488,6 +499,20 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} API response or ErrorResponse */ + async makeRequest( + context: RequestHandlerContext, + method: 'GET' | 'POST' | 'PUT' | 'DELETE', + path: string, + data: { + devTools?: boolean; + delay?: number; + headers?: Record; + origin?: string; + body?: any; + }, + id: string, + response: object, + ) { const devTools = !!data?.devTools; try { let api; From 00867d0b4e3ae73490efcfd9c02ce3d2af2c8b8f Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 07:34:13 -0300 Subject: [PATCH 14/33] Remove unnecessary code for checking API availability.- Remove redundant variable assignment.- Remove commented out code for checking API parameters.- Simplify logic for handling missing API data --- plugins/main/server/controllers/wazuh-api.ts | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 5293dce6a6..2e11f7d9be 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -318,17 +318,12 @@ export class WazuhApiCtrl { response: OpenSearchDashboardsResponseFactory, ) { try { - let apiAvailable = null; - // const notValid = this.validateCheckApiParams(request.body); - // if (notValid) return ErrorResponse(notValid, 3003, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response); context.wazuh.logger.debug(`${request.body.id} is valid`); // Check if a Wazuh API id is given (already stored API) const data = await context.wazuh_core.manageHosts.get(request.body.id, { excludePassword: true, }); - if (data) { - apiAvailable = data; - } else { + if (!data) { const errorMessage = `The server API host entry with ID ${request.body.id} was not found`; context.wazuh.logger.debug(errorMessage); return ErrorResponse( From f5e8e8c3506d1d7f3025a95b2aa8d4514d7dad98 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 11:01:18 -0300 Subject: [PATCH 15/33] Refactor route handlers to use async/await functions --- plugins/main/server/routes/wazuh-api.ts | 26 ++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/plugins/main/server/routes/wazuh-api.ts b/plugins/main/server/routes/wazuh-api.ts index c44b16a3c5..9e0e2cc1bd 100644 --- a/plugins/main/server/routes/wazuh-api.ts +++ b/plugins/main/server/routes/wazuh-api.ts @@ -16,7 +16,8 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.checkStoredAPI, + async (context, request, response) => + ctrl.checkStoredAPI(context, request, response), ); // Check if credentials on POST connect to Wazuh API. Not storing them! @@ -43,7 +44,8 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.checkAPI, + async (context, request, response) => + ctrl.checkAPI(context, request, response), ); router.post( @@ -56,7 +58,8 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.getToken, + async (context, request, response) => + ctrl.getToken(context, request, response), ); // Returns the request result (With error control) @@ -72,7 +75,8 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.requestApi, + async (context, request, response) => + ctrl.requestApi(context, request, response), ); // Returns data from the Wazuh API on CSV readable format @@ -87,7 +91,7 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.csv, + async (context, request, response) => ctrl.csv(context, request, response), ); // Returns a route list used by the Dev Tools @@ -96,7 +100,8 @@ export function WazuhApiRoutes(router: IRouter) { path: '/api/routes', validate: false, }, - ctrl.getRequestList, + async (context, request, response) => + ctrl.getRequestList(context, request, response), ); // Return Wazuh Appsetup info @@ -105,7 +110,8 @@ export function WazuhApiRoutes(router: IRouter) { path: '/api/setup', validate: false, }, - ctrl.getSetupInfo, + async (context, request, response) => + ctrl.getSetupInfo(context, request, response), ); // Return basic information of syscollector for given agent @@ -118,7 +124,8 @@ export function WazuhApiRoutes(router: IRouter) { }), }, }, - ctrl.getSyscollector, + async (context, request, response) => + ctrl.getSyscollector(context, request, response), ); // Return app logos configuration @@ -128,6 +135,7 @@ export function WazuhApiRoutes(router: IRouter) { validate: false, options: { authRequired: false }, }, - ctrl.getAppLogos, + async (context, request, response) => + ctrl.getAppLogos(context, request, response), ); } From 51890e7406b52661d64502859694d923618310f5 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 11:41:25 -0300 Subject: [PATCH 16/33] Refactor error handling to log messages as strings --- plugins/main/server/controllers/wazuh-api.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 2e11f7d9be..ef6efb0835 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -406,7 +406,7 @@ export class WazuhApiCtrl { ); } return ErrorResponse( - (error as Error).message || error, + ((error as Error).message || error) as string, 3005, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -577,7 +577,7 @@ export class WazuhApiCtrl { } catch (error) { contextJob.wazuh.logger.error( `An error ocurred in the delayed request: "${method} ${path}": ${ - (error as Error).message || error + ((error as Error).message || error) as string }`, ); } @@ -915,9 +915,9 @@ export class WazuhApiCtrl { ); } } catch (error) { - context.wazuh.logger.error((error as Error).message || error); + context.wazuh.logger.error(((error as Error).message || error) as string); return ErrorResponse( - (error as Error).message || error, + ((error as Error).message || error) as string, 3034, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -961,10 +961,10 @@ export class WazuhApiCtrl { }, }); } catch (error) { - context.wazuh.logger.error((error as Error).message || error); + context.wazuh.logger.error(((error as Error).message || error) as string); return ErrorResponse( `Could not get data from wazuh-version registry due to ${ - (error as Error).message || error + ((error as Error).message || error) as string }`, 4005, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, @@ -1028,9 +1028,9 @@ export class WazuhApiCtrl { body: syscollector, }); } catch (error) { - context.wazuh.logger.error((error as Error).message || error); + context.wazuh.logger.error(((error as Error).message || error) as string); return ErrorResponse( - (error as Error).message || error, + ((error as Error).message || error) as string, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, @@ -1068,9 +1068,9 @@ export class WazuhApiCtrl { body: { logos }, }); } catch (error) { - context.wazuh.logger.error((error as Error).message || error); + context.wazuh.logger.error(((error as Error).message || error) as string); return ErrorResponse( - (error as Error).message || error, + ((error as Error).message || error) as string, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response, From 2cf4394ab938adbcb789339026431daf3dd3127f Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 11:44:47 -0300 Subject: [PATCH 17/33] Update OpenSearchDashboardsRequest and response types --- plugins/main/server/controllers/wazuh-api.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index ef6efb0835..76e5bbda93 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -142,7 +142,7 @@ export class WazuhApiCtrl { */ async checkStoredAPI( context: RequestHandlerContext, - request: OpenSearchDashboardsRequest, + request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory, ) { try { @@ -314,7 +314,7 @@ export class WazuhApiCtrl { */ async checkAPI( context: RequestHandlerContext, - request: OpenSearchDashboardsRequest, + request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory, ) { try { @@ -506,7 +506,7 @@ export class WazuhApiCtrl { body?: any; }, id: string, - response: object, + response: OpenSearchDashboardsResponseFactory, ) { const devTools = !!data?.devTools; try { From 32ef2ac00e8125514d10d60d65d48c57895f1bb4 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 12:08:04 -0300 Subject: [PATCH 18/33] Update limit parameter type to Record. --- plugins/main/server/controllers/wazuh-api.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 76e5bbda93..21090fcc0f 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -785,7 +785,7 @@ export class WazuhApiCtrl { context.wazuh.logger.debug(`Report ${tmpPath}`); // Real limit, regardless the user query - const params = { limit: 500 }; + const params: Record = { limit: 500 }; if (filters.length) { for (const filter of filters) { From 75ea03e13f1b6648d27638a62e55e5d18360cf49 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 12:08:35 -0300 Subject: [PATCH 19/33] Update json2csvParser fields mapping in WazuhApiCtrl class --- plugins/main/server/controllers/wazuh-api.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 21090fcc0f..60172511c5 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -882,12 +882,15 @@ export class WazuhApiCtrl { fields = ['key', 'value']; itemsArray = output.data.data.affected_items[0].items; } - fields = fields.map(item => ({ value: item, default: '-' })); + const fieldsMapped = fields.map(item => ({ + value: item, + default: '-', + })); - const json2csvParser = new Parser({ fields }); + const json2csvParser = new Parser({ fields: fieldsMapped }); let csv = json2csvParser.parse(itemsArray); - for (const field of fields) { + for (const field of fieldsMapped) { const { value } = field; if (csv.includes(value)) { csv = csv.replace(value, KeyEquivalence[value] || value); From 9d65d97353238d1bf8ca63b364b6cf33b44d02ed Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 12:19:22 -0300 Subject: [PATCH 20/33] Refactor handling of Wazuh API requests --- plugins/main/server/controllers/wazuh-api.ts | 65 ++++++++++++-------- 1 file changed, 40 insertions(+), 25 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 60172511c5..b34bf96e87 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -319,42 +319,57 @@ export class WazuhApiCtrl { ) { try { context.wazuh.logger.debug(`${request.body.id} is valid`); - // Check if a Wazuh API id is given (already stored API) - const data = await context.wazuh_core.manageHosts.get(request.body.id, { - excludePassword: true, - }); - if (!data) { - const errorMessage = `The server API host entry with ID ${request.body.id} was not found`; - context.wazuh.logger.debug(errorMessage); - return ErrorResponse( - errorMessage, - 3029, - HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response, - ); - } const options: { apiHostID: string; forceRefresh?: boolean } = { apiHostID: request.body.id, }; if (request.body.forceRefresh) { options['forceRefresh'] = request.body.forceRefresh; } - let responseManagerInfo; - try { - responseManagerInfo = - await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/manager/info`, - {}, - options, + const promises = [ + context.wazuh_core.manageHosts.get(request.body.id, { + excludePassword: true, + }), + context.wazuh.api.client.asInternalUser.request( + 'GET', + `/manager/info`, + {}, + options, + ), + ]; + + let data; + const settledResults = await Promise.allSettled(promises); + + if (settledResults[0].status === 'fulfilled') { + // Check if a Wazuh API id is given (already stored API) + data = settledResults[0].value; + + if (!data) { + const errorMessage = `The server API host entry with ID ${request.body.id} was not found`; + context.wazuh.logger.debug(errorMessage); + return ErrorResponse( + errorMessage, + 3029, + HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, + response, ); - } catch (error) { + } + } else { + throw new Error(settledResults[0].reason); + } + + let responseManagerInfo; + if (settledResults[1].status === 'fulfilled') { + responseManagerInfo = settledResults[1].value; + } else { return ErrorResponse( `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ - error.response?.data?.detail || this.SERVER_NOT_READY_YET + settledResults[1].reason.response?.data?.detail || + this.SERVER_NOT_READY_YET }`, 3099, - error?.response?.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, + settledResults[1].reason?.response?.status || + HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, response, ); } From a3caa448bde5895a06d541f0f696814772a0fee9 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 13:27:30 -0300 Subject: [PATCH 21/33] Fix Prettier issue: --- plugins/main/common/constants.ts | 2 +- .../components/management/configuration/utils/wz-fetch.js | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/plugins/main/common/constants.ts b/plugins/main/common/constants.ts index 8ec19b6eb3..d060bcedee 100644 --- a/plugins/main/common/constants.ts +++ b/plugins/main/common/constants.ts @@ -531,4 +531,4 @@ export const OSD_URL_STATE_STORAGE_ID = 'state:storeInSessionStorage'; export enum ERROR_CODES { EPROTO = 'EPROTO', ECONNREFUSED = 'ECONNREFUSED', -}; +} diff --git a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js index 848a7915c5..6be6009d1a 100644 --- a/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js +++ b/plugins/main/public/controllers/management/components/management/configuration/utils/wz-fetch.js @@ -14,7 +14,10 @@ import { WzRequest } from '../../../../../../react-services/wz-request'; import { replaceIllegalXML } from './xml'; import { getToasts } from '../../../../../../kibana-services'; import { delayAsPromise } from '../../../../../../../common/utils'; -import { AGENT_SYNCED_STATUS, WAZUH_ERROR_DAEMONS_NOT_READY } from '../../../../../../../common/constants'; +import { + AGENT_SYNCED_STATUS, + WAZUH_ERROR_DAEMONS_NOT_READY, +} from '../../../../../../../common/constants'; /** * Get configuration for an agent/manager of request sections From fa8bea5a97c8d36a3b919410ae988c8b012ac051 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 14:00:33 -0300 Subject: [PATCH 22/33] Add mock for API client's asInternalUser endpoint --- plugins/main/server/routes/wazuh-api-http-status.test.ts | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/plugins/main/server/routes/wazuh-api-http-status.test.ts b/plugins/main/server/routes/wazuh-api-http-status.test.ts index 977cf2c43a..6a6c578e4d 100644 --- a/plugins/main/server/routes/wazuh-api-http-status.test.ts +++ b/plugins/main/server/routes/wazuh-api-http-status.test.ts @@ -21,6 +21,15 @@ const context = { warn: jest.fn(), error: jest.fn(), }, + api: { + client: { + asInternalUser: { + request: jest.fn().mockRejectedValue({ + response: {}, + }), + }, + }, + }, }, wazuh_core: { manageHosts: { From 8c6e364e16ff519c9403d3c7b378ba2fe7c9c486 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 14:16:09 -0300 Subject: [PATCH 23/33] Update error handling in WazuhApiCtrl class --- plugins/main/server/controllers/wazuh-api.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index b34bf96e87..97da674622 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -362,14 +362,13 @@ export class WazuhApiCtrl { if (settledResults[1].status === 'fulfilled') { responseManagerInfo = settledResults[1].value; } else { + const error = settledResults[1].reason; return ErrorResponse( `${WAZUH_ERROR_DAEMONS_NOT_READY} - ${ - settledResults[1].reason.response?.data?.detail || - this.SERVER_NOT_READY_YET + error.response?.data?.detail || this.SERVER_NOT_READY_YET }`, 3099, - settledResults[1].reason?.response?.status || - HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, + error?.response?.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, response, ); } From 90421cf3adfc8f5c41fb05432b2a5d805eb1e9f8 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:27:14 -0300 Subject: [PATCH 24/33] Update WazuhCorePluginStart type in kibana-services.ts --- plugins/main/public/kibana-services.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/main/public/kibana-services.ts b/plugins/main/public/kibana-services.ts index 1c536dc5e1..cb3f44bdaa 100644 --- a/plugins/main/public/kibana-services.ts +++ b/plugins/main/public/kibana-services.ts @@ -15,6 +15,7 @@ import { VisualizationsStart } from '../../../src/plugins/visualizations/public' import { NavigationPublicPluginStart } from '../../../src/plugins/navigation/public'; import { AppPluginStartDependencies } from './types'; import { WazuhCheckUpdatesPluginStart } from '../../wazuh-check-updates/public'; +import { WazuhCorePluginStart } from 'plugins/wazuh-core/public'; let angularModule: any = null; let discoverModule: any = null; @@ -46,7 +47,7 @@ export const [getWzCurrentAppID, setWzCurrentAppID] = export const [getWazuhCheckUpdatesPlugin, setWazuhCheckUpdatesPlugin] = createGetterSetter('WazuhCheckUpdatesPlugin'); export const [getWazuhCorePlugin, setWazuhCorePlugin] = - createGetterSetter('WazuhCorePlugin'); + createGetterSetter('WazuhCorePlugin'); export const [getHeaderActionMenuMounter, setHeaderActionMenuMounter] = createGetterSetter( 'headerActionMenuMounter', From efe7ac16bea20ce38039cf15305fe1d446f6795e Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:32:03 -0300 Subject: [PATCH 25/33] Add WzToken interface and adjust cookie value retrieval --- plugins/main/server/controllers/types.ts | 10 ++++++++++ plugins/main/server/controllers/wazuh-api.ts | 21 +++++++++++++------- 2 files changed, 24 insertions(+), 7 deletions(-) create mode 100644 plugins/main/server/controllers/types.ts diff --git a/plugins/main/server/controllers/types.ts b/plugins/main/server/controllers/types.ts new file mode 100644 index 0000000000..41d271539c --- /dev/null +++ b/plugins/main/server/controllers/types.ts @@ -0,0 +1,10 @@ +export interface WzToken { + iss: string; + aud: string; + nbf: number; + exp: number; + sub: string; + run_as: boolean; + rbac_roles: number[]; + rbac_mode: string; +} diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 97da674622..a4b0273f5c 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -15,7 +15,7 @@ import { ErrorResponse } from '../lib/error-response'; import { Parser } from 'json2csv'; import { KeyEquivalence } from '../../common/csv-key-equivalence'; import { ApiErrorEquivalence } from '../lib/api-errors-equivalence'; -import apiRequestList from '../../common/api-info/endpoints'; +import apiRequestList from '../../common/api-info/endpoints.json'; import { ERROR_CODES, HTTP_STATUS_CODES, @@ -27,12 +27,13 @@ import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory, -} from 'src/core/server'; +} from '../../../../src/core/server'; import { getCookieValueByName } from '../lib/cookie'; import { version as pluginVersion, revision as pluginRevision, } from '../../package.json'; +import { WzToken } from './types'; export class WazuhApiCtrl { private readonly SERVER_API_PENDING_INITIALIZATION = @@ -45,7 +46,11 @@ export class WazuhApiCtrl { async getToken( context: RequestHandlerContext, - request: OpenSearchDashboardsRequest, + request: OpenSearchDashboardsRequest< + unknown, + unknown, + { force: boolean; idHost: string } + >, response: OpenSearchDashboardsResponseFactory, ) { try { @@ -59,18 +64,20 @@ export class WazuhApiCtrl { request.headers.cookie && username === decodeURIComponent( - getCookieValueByName(request.headers.cookie, 'wz-user') ?? '', + getCookieValueByName(request.headers.cookie as string, 'wz-user') ?? + '', ) && - idHost === getCookieValueByName(request.headers.cookie, 'wz-api') + idHost === + getCookieValueByName(request.headers.cookie as string, 'wz-api') ) { const wzToken = getCookieValueByName( - request.headers.cookie, + request.headers.cookie as string, 'wz-token', ); if (wzToken) { try { // if the current token is not a valid jwt token we ask for a new one - const decodedToken = jwtDecode(wzToken); + const decodedToken = jwtDecode(wzToken); const expirationTime = decodedToken.exp - Date.now() / 1000; if (wzToken && expirationTime > 0) { return response.ok({ From 74ca6d1cf650dfe0300e8be677f1dfe5be54619a Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:32:27 -0300 Subject: [PATCH 26/33] Refactor route decorators for administrator & configuration API --- plugins/main/server/controllers/decorators.ts | 35 ++++++++++++++++--- 1 file changed, 30 insertions(+), 5 deletions(-) diff --git a/plugins/main/server/controllers/decorators.ts b/plugins/main/server/controllers/decorators.ts index e3f2c90ddf..1ca3f62df0 100644 --- a/plugins/main/server/controllers/decorators.ts +++ b/plugins/main/server/controllers/decorators.ts @@ -1,8 +1,23 @@ +import { + OpenSearchDashboardsRequest, + OpenSearchDashboardsResponseFactory, + RequestHandlerContext, +} from 'opensearch-dashboards/server'; import { ErrorResponse } from '../lib/error-response'; export function routeDecoratorProtectedAdministrator(errorCode: number) { - return handler => { - return async (context, request, response) => { + return ( + handler: ( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) => Promise, + ) => { + return async ( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) => { try { const { administrator, administrator_requirements } = await context.wazuh_core.dashboardSecurity.isAdministratorUser( @@ -20,9 +35,19 @@ export function routeDecoratorProtectedAdministrator(errorCode: number) { }; } -export function routeDecoratorConfigurationAPIEditable(errorCode) { - return handler => { - return async (context, request, response) => { +export function routeDecoratorConfigurationAPIEditable(errorCode: number) { + return ( + handler: ( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) => Promise, + ) => { + return async ( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) => { try { const canEditConfiguration = await context.wazuh_core.configuration.get( 'configuration.ui_api_editable', From 3880d7b9a31610f140f75f5d34eca8911e5494f2 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:32:37 -0300 Subject: [PATCH 27/33] Update import path for PluginInitializerContext --- plugins/main/server/index.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/server/index.ts b/plugins/main/server/index.ts index b9ce06ee35..0d1971bde6 100644 --- a/plugins/main/server/index.ts +++ b/plugins/main/server/index.ts @@ -1,4 +1,4 @@ -import { PluginInitializerContext } from 'opensearch_dashboards/server'; +import { PluginInitializerContext } from '../../../src/core/server'; import { WazuhPlugin } from './plugin'; From 865253aa1dd7369f5e19141da982bdd64f4ed503 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:33:54 -0300 Subject: [PATCH 28/33] Add resolveJsonModule to compilerOptions in tsconfig.json --- plugins/main/tsconfig.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/plugins/main/tsconfig.json b/plugins/main/tsconfig.json index 63e20a2cf0..f6ee2db643 100644 --- a/plugins/main/tsconfig.json +++ b/plugins/main/tsconfig.json @@ -1,4 +1,9 @@ { "extends": "../../tsconfig.json", - "include": ["./**/*"] + "include": [ + "./**/*" + ], + "compilerOptions": { + "resolveJsonModule": true + } } From 7af27d560c2a77c862ba328cd26f477634737e31 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Wed, 16 Oct 2024 18:38:03 -0300 Subject: [PATCH 29/33] Add types and interfaces for WazuhCore and configuration --- plugins/main/common/types.ts | 199 ++++++++++++++++++++++++++++++++++ plugins/main/public/types.ts | 2 + plugins/main/server/plugin.ts | 53 ++++----- plugins/main/server/types.ts | 4 +- 4 files changed, 232 insertions(+), 26 deletions(-) create mode 100644 plugins/main/common/types.ts diff --git a/plugins/main/common/types.ts b/plugins/main/common/types.ts new file mode 100644 index 0000000000..9c61d2c3da --- /dev/null +++ b/plugins/main/common/types.ts @@ -0,0 +1,199 @@ +import { RequestHandlerContext } from 'opensearch-dashboards/server'; +import type { ManageHosts } from "../../wazuh-core/server/services"; +import { OpenSearchDashboardsRequest } from 'src/core/server/http'; + +export type UserAuthenticate = (apiHostID: string) => Promise; + +export type UserRequestOptions = { apiHostID: string; forceRefresh?: boolean }; +export type UserRequest = ( + method: string, + path: string, + data: any, + options: UserRequestOptions +) => Promise; + +export type AsUser = { + authenticate: UserAuthenticate; + request: UserRequest; +}; + +export type ApiClient = { + asInternalUser: AsUser; + asCurrentUser: AsUser; +}; + +type CurrentUser = { + username?: string; + authContext: { [key: string]: any }; +}; + +export interface ISecurityFactory { + platform?: string; + getCurrentUser( + request: OpenSearchDashboardsRequest, + context?: RequestHandlerContext + ): Promise; + isAdministratorUser( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest + ): Promise<{ administrator: any; administrator_requirements: any }>; +} + +export enum EpluginSettingType { + text = 'text', + password = 'password', + textarea = 'textarea', + switch = 'switch', + number = 'number', + editor = 'editor', + select = 'select', + filepicker = 'filepicker', +} + +type TConfigurationSettingOptionsPassword = { + password: { + dual?: 'text' | 'password' | 'dual'; + }; +}; + +type TConfigurationSettingOptionsTextArea = { + maxRows?: number; + minRows?: number; + maxLength?: number; +}; + +type TConfigurationSettingOptionsSelect = { + select: { text: string; value: any }[]; +}; + +type TConfigurationSettingOptionsEditor = { + editor: { + language: string; + }; +}; + +type TConfigurationSettingOptionsFile = { + file: { + type: 'image'; + extensions?: string[]; + size?: { + maxBytes?: number; + minBytes?: number; + }; + recommended?: { + dimensions?: { + width: number; + height: number; + unit: string; + }; + }; + store?: { + relativePathFileSystem: string; + filename: string; + resolveStaticURL: (filename: string) => string; + }; + }; +}; + +type TConfigurationSettingOptionsNumber = { + number: { + min?: number; + max?: number; + integer?: boolean; + }; +}; + +type TConfigurationSettingOptionsSwitch = { + switch: { + values: { + disabled: { label?: string; value: any }; + enabled: { label?: string; value: any }; + }; + }; +}; + +export type TConfigurationSetting = { + // Define the text displayed in the UI. + title: string; + // Description. + description: string; + // Category. + category: number; + // Type. + type: EpluginSettingType; + // Default value. + defaultValue: any; + /* Special: This is used for the settings of customization to get the hidden default value, because the default value is empty to not to be displayed on the App Settings. */ + defaultValueIfNotSet?: any; + // Configurable from the configuration file. + isConfigurableFromSettings: boolean; + // Modify the setting requires running the plugin health check (frontend). + requiresRunningHealthCheck?: boolean; + // Modify the setting requires reloading the browser tab (frontend). + requiresReloadingBrowserTab?: boolean; + // Modify the setting requires restarting the plugin platform to take effect. + requiresRestartingPluginPlatform?: boolean; + // Define options related to the `type`. + options?: + | TConfigurationSettingOptionsEditor + | TConfigurationSettingOptionsFile + | TConfigurationSettingOptionsNumber + | TConfigurationSettingOptionsPassword + | TConfigurationSettingOptionsSelect + | TConfigurationSettingOptionsSwitch + | TConfigurationSettingOptionsTextArea; + store?: { + file: { + // Define if the setting is managed by the ConfigurationStore service + configurableManaged?: boolean; + // Define a text to print as the default in the configuration block + defaultBlock?: string; + /* Transform the value defined in the configuration file to be consumed by the Configuration + service */ + transformFrom?: (value: any) => any; + }; + }; + // Transform the input value. The result is saved in the form global state of Settings/Configuration + uiFormTransformChangedInputValue?: (value: any) => any; + // Transform the configuration value or default as initial value for the input in Settings/Configuration + uiFormTransformConfigurationValueToInputValue?: (value: any) => any; + // Transform the input value changed in the form of Settings/Configuration and returned in the `changed` property of the hook useForm + uiFormTransformInputValueToConfigurationValue?: (value: any) => any; + // Validate the value in the form of App Settings. It returns a string if there is some validation error. + validateUIForm?: (value: any) => string | undefined; + // Validate function creator to validate the setting in the backend. + validate?: (value: string) => string | undefined; +}; + +type TConfigurationSettings = { [key: string]: any }; +export interface IConfigurationStore { + setup: () => Promise; + start: () => Promise; + stop: () => Promise; + get: (...settings: string[]) => Promise; + set: (settings: TConfigurationSettings) => Promise; + clear: (...settings: string[]) => Promise; + setConfiguration: (configuration: IConfiguration) => void; +} + +export interface IConfiguration { + setStore(store: IConfigurationStore): void; + setup(): Promise; + start(): Promise; + stop(): Promise; + register(id: string, value: any): void; + get(...settings: string[]): Promise; + set(settings: TConfigurationSettings): Promise; + clear(...settings: string[]): Promise; + reset(...settings: string[]): Promise; + _settings: Map; + getSettingValue(settingKey: string, value?: any): any; + getSettingValueIfNotSet(settingKey: string, value?: any): any; +} + +export type WazuhCore = { + api: { client: ApiClient }; + dashboardSecurity: ISecurityFactory; + configuration: IConfiguration; + manageHosts: ManageHosts; +}; diff --git a/plugins/main/public/types.ts b/plugins/main/public/types.ts index 9d3c0e7915..dfefa22227 100644 --- a/plugins/main/public/types.ts +++ b/plugins/main/public/types.ts @@ -20,6 +20,7 @@ import { import { WazuhCheckUpdatesPluginStart } from '../../wazuh-check-updates/public'; import { WazuhCorePluginStart } from '../../wazuh-core/public'; import { DashboardStart } from '../../../src/plugins/dashboard/public'; +import { WazuhCore } from '../common/types'; export interface AppPluginStartDependencies { navigation: NavigationPublicPluginStart; @@ -46,6 +47,7 @@ export type WazuhSetupPlugins = { data: DataPublicPluginSetup; navigation: NavigationPublicPluginStart; telemetry: TelemetryPluginSetup; + wazuhCore: WazuhCore; }; export type WazuhStartPlugins = AppPluginStartDependencies; diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index e37ec01792..b039287d13 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -24,9 +24,16 @@ import { Plugin, PluginInitializerContext, SharedGlobalConfig, -} from 'opensearch_dashboards/server'; + OpenSearchDashboardsRequest, +} from '../../../src/core/server'; -import { WazuhPluginSetup, WazuhPluginStart, PluginSetup } from './types'; +import { + WazuhPluginSetup, + WazuhPluginStart, + PluginSetup, + ApiClient, + DashboardSecurity, +} from './types'; import { setupRoutes } from './routes'; import { jobInitializeRun, @@ -37,36 +44,32 @@ import { jobSanitizeUploadedFilesTasksRun, } from './start'; import { first } from 'rxjs/operators'; +import { WazuhCore } from '../common/types'; -declare module 'opensearch_dashboards/server' { +declare module '../../../src/core/server' { interface RequestHandlerContext { wazuh: { logger: Logger; plugins: PluginSetup; - security: any; + security: DashboardSecurity; api: { - client: { - asInternalUser: { - authenticate: (apiHostID: string) => Promise; - request: ( - method: string, - path: string, - data: any, - options: { apiHostID: string; forceRefresh?: boolean }, - ) => Promise; - }; - asCurrentUser: { - authenticate: (apiHostID: string) => Promise; - request: ( - method: string, - path: string, - data: any, - options: { apiHostID: string; forceRefresh?: boolean }, - ) => Promise; - }; + client: ApiClient; + }; + server: { + info: { + name: string; + hostname: string; + port: number; + protocol: string; }; }; }; + wazuhEndpointParams: { + pathFilename: string; + hashUsername: string; + filename: string; + }; + wazuh_core: PluginSetup['wazuhCore']; } } @@ -93,7 +96,7 @@ export class WazuhPlugin implements Plugin { }, plugins, security: plugins.wazuhCore.dashboardSecurity, - api: context.wazuh_core.api, + api: context.wazuh_core?.api as WazuhCore['api'], }; }); @@ -112,7 +115,7 @@ export class WazuhPlugin implements Plugin { return {}; } - public async start(core: CoreStart, plugins: any) { + public async start(core: CoreStart, plugins: { wazuhCore: WazuhCore }) { const globalConfiguration: SharedGlobalConfig = await this.initializerContext.config.legacy.globalConfig$ .pipe(first()) diff --git a/plugins/main/server/types.ts b/plugins/main/server/types.ts index 2095695534..875c3b01af 100644 --- a/plugins/main/server/types.ts +++ b/plugins/main/server/types.ts @@ -17,11 +17,13 @@ * under the License. */ +import { WazuhCore } from '../common/types'; + export interface WazuhPluginSetup {} export interface WazuhPluginStart {} export type PluginSetup = { securityDashboards?: {}; // TODO: Add OpenSearch Dashboards Security interface - wazuhCore: {}; + wazuhCore: WazuhCore; }; From e1527493503ec0fc6eb4f6af4182105e42cfd65c Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Thu, 17 Oct 2024 08:18:43 -0300 Subject: [PATCH 30/33] Fix Prettier issue --- plugins/main/common/types.ts | 8 ++++---- plugins/main/tsconfig.json | 4 +--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/plugins/main/common/types.ts b/plugins/main/common/types.ts index 9c61d2c3da..1c0a05d693 100644 --- a/plugins/main/common/types.ts +++ b/plugins/main/common/types.ts @@ -1,5 +1,5 @@ import { RequestHandlerContext } from 'opensearch-dashboards/server'; -import type { ManageHosts } from "../../wazuh-core/server/services"; +import type { ManageHosts } from '../../wazuh-core/server/services'; import { OpenSearchDashboardsRequest } from 'src/core/server/http'; export type UserAuthenticate = (apiHostID: string) => Promise; @@ -9,7 +9,7 @@ export type UserRequest = ( method: string, path: string, data: any, - options: UserRequestOptions + options: UserRequestOptions, ) => Promise; export type AsUser = { @@ -31,11 +31,11 @@ export interface ISecurityFactory { platform?: string; getCurrentUser( request: OpenSearchDashboardsRequest, - context?: RequestHandlerContext + context?: RequestHandlerContext, ): Promise; isAdministratorUser( context: RequestHandlerContext, - request: OpenSearchDashboardsRequest + request: OpenSearchDashboardsRequest, ): Promise<{ administrator: any; administrator_requirements: any }>; } diff --git a/plugins/main/tsconfig.json b/plugins/main/tsconfig.json index f6ee2db643..1f78e879f9 100644 --- a/plugins/main/tsconfig.json +++ b/plugins/main/tsconfig.json @@ -1,8 +1,6 @@ { "extends": "../../tsconfig.json", - "include": [ - "./**/*" - ], + "include": ["./**/*"], "compilerOptions": { "resolveJsonModule": true } From 5df83468a7c783840042bf9ef9766e377fb191a8 Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Thu, 31 Oct 2024 08:39:10 -0300 Subject: [PATCH 31/33] Update CHANGELOG to reflect changes in loading speed, clarifying backend optimizations for reduced latency. #7099 --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a11bb5f7f3..d616066ab6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -37,7 +37,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Fixed vulnerabilities inventory table scroll [#7118](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7118) - Fixed the filter are displayed cropped on screens of 575px to 767px in vulnerability detection module [#7047](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7047) - Fixed ability to filter from files inventory details flyout of File Integrity Monitoring [#7119](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7119) -- Fixed loading speed [#7099](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7099) +- Fixed backend endpoints to reduce initial load time by minimizing latency in network requests. [#7099](https://github.com/wazuh/wazuh-dashboard-plugins/pull/7099) ### Removed From 6e1d2d76bf8f1cfc52f463aaba5e7b39d5bbc99a Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Thu, 31 Oct 2024 08:42:03 -0300 Subject: [PATCH 32/33] Refactor tsconfig.json formatting: clean up include array and remove unnecessary compilerOptions for clarity --- plugins/main/tsconfig.json | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/plugins/main/tsconfig.json b/plugins/main/tsconfig.json index 1f78e879f9..189eab2321 100644 --- a/plugins/main/tsconfig.json +++ b/plugins/main/tsconfig.json @@ -1,7 +1,6 @@ { "extends": "../../tsconfig.json", - "include": ["./**/*"], - "compilerOptions": { - "resolveJsonModule": true - } + "include": [ + "./**/*" + ] } From 686f134904f52b5bfc8e7f9171003b5089d8355b Mon Sep 17 00:00:00 2001 From: Guido Modarelli Date: Thu, 31 Oct 2024 09:18:50 -0300 Subject: [PATCH 33/33] Make wazuhEndpointParams optional in plugin.ts to improve flexibility in configuration settings --- plugins/main/server/plugin.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/main/server/plugin.ts b/plugins/main/server/plugin.ts index b039287d13..fa9b97282a 100644 --- a/plugins/main/server/plugin.ts +++ b/plugins/main/server/plugin.ts @@ -64,7 +64,7 @@ declare module '../../../src/core/server' { }; }; }; - wazuhEndpointParams: { + wazuhEndpointParams?: { pathFilename: string; hashUsername: string; filename: string;