From 404112b78fdb113a2c06ec8c49453bfaa856ee90 Mon Sep 17 00:00:00 2001 From: Tostti Date: Mon, 30 Oct 2023 12:34:42 -0300 Subject: [PATCH 1/3] add enconding to user name for api --- plugins/main/server/controllers/wazuh-api.ts | 735 +++++++++++++------ 1 file changed, 502 insertions(+), 233 deletions(-) diff --git a/plugins/main/server/controllers/wazuh-api.ts b/plugins/main/server/controllers/wazuh-api.ts index 2dc0e1bb13..cb3613dd06 100644 --- a/plugins/main/server/controllers/wazuh-api.ts +++ b/plugins/main/server/controllers/wazuh-api.ts @@ -24,34 +24,61 @@ import fs from 'fs'; import { ManageHosts } from '../lib/manage-hosts'; import { UpdateRegistry } from '../lib/update-registry'; import jwtDecode from 'jwt-decode'; -import { OpenSearchDashboardsRequest, RequestHandlerContext, OpenSearchDashboardsResponseFactory } from 'src/core/server'; -import { APIUserAllowRunAs, CacheInMemoryAPIUserAllowRunAs, API_USER_STATUS_RUN_AS } from '../lib/cache-api-user-has-run-as'; +import { + OpenSearchDashboardsRequest, + RequestHandlerContext, + OpenSearchDashboardsResponseFactory, +} from 'src/core/server'; +import { + APIUserAllowRunAs, + CacheInMemoryAPIUserAllowRunAs, + API_USER_STATUS_RUN_AS, +} from '../lib/cache-api-user-has-run-as'; import { getCookieValueByName } from '../lib/cookie'; import { SecurityObj } from '../lib/security-factory'; import { getConfiguration } from '../lib/get-configuration'; export class WazuhApiCtrl { - manageHosts: ManageHosts - updateRegistry: UpdateRegistry + manageHosts: ManageHosts; + updateRegistry: UpdateRegistry; constructor() { this.manageHosts = new ManageHosts(); this.updateRegistry = new UpdateRegistry(); } - async getToken(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async getToken( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { const { force, idHost } = request.body; - const { username } = await context.wazuh.security.getCurrentUser(request, context); - if (!force && request.headers.cookie && username === getCookieValueByName(request.headers.cookie, 'wz-user') && idHost === getCookieValueByName(request.headers.cookie,'wz-api')) { - const wzToken = getCookieValueByName(request.headers.cookie, 'wz-token'); + const { username } = await context.wazuh.security.getCurrentUser( + request, + context, + ); + if ( + !force && + request.headers.cookie && + username === + decodeURIComponent( + getCookieValueByName(request.headers.cookie, 'wz-user'), + ) && + idHost === getCookieValueByName(request.headers.cookie, 'wz-api') + ) { + const wzToken = getCookieValueByName( + request.headers.cookie, + 'wz-token', + ); if (wzToken) { - try { // if the current token is not a valid jwt token we ask for a new one + try { + // if the current token is not a valid jwt token we ask for a new one const decodedToken = jwtDecode(wzToken); - const expirationTime = (decodedToken.exp - (Date.now() / 1000)); + const expirationTime = decodedToken.exp - Date.now() / 1000; if (wzToken && expirationTime > 0) { return response.ok({ - body: { token: wzToken } + body: { token: wzToken }, }); } } catch (error) { @@ -60,35 +87,43 @@ export class WazuhApiCtrl { } } let token; - if (await APIUserAllowRunAs.canUse(idHost) == API_USER_STATUS_RUN_AS.ENABLED) { - token = await context.wazuh.api.client.asCurrentUser.authenticate(idHost); + if ( + (await APIUserAllowRunAs.canUse(idHost)) == + API_USER_STATUS_RUN_AS.ENABLED + ) { + token = await context.wazuh.api.client.asCurrentUser.authenticate( + idHost, + ); } else { - token = await context.wazuh.api.client.asInternalUser.authenticate(idHost); - }; + token = await context.wazuh.api.client.asInternalUser.authenticate( + idHost, + ); + } - let textSecure=''; - if(context.wazuh.server.info.protocol === 'https'){ + let textSecure = ''; + if (context.wazuh.server.info.protocol === 'https') { textSecure = ';Secure'; } - + const encodedUser = encodeURIComponent(username); return response.ok({ headers: { 'set-cookie': [ `wz-token=${token};Path=/;HttpOnly${textSecure}`, - `wz-user=${username};Path=/;HttpOnly${textSecure}`, + `wz-user=${encodedUser};Path=/;HttpOnly${textSecure}`, `wz-api=${idHost};Path=/;HttpOnly`, ], }, - body: { token } + body: { token }, }); } catch (error) { - const errorMessage = ((error.response || {}).data || {}).detail || error.message || error; + const errorMessage = + ((error.response || {}).data || {}).detail || error.message || error; log('wazuh-api:getToken', errorMessage); return ErrorResponse( `Error getting the authorization token: ${errorMessage}`, 3000, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -100,7 +135,11 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} status obj or ErrorResponse */ - async checkStoredAPI(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async checkStoredAPI( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { // Get config from wazuh.yml const id = request.body.id; @@ -113,59 +152,72 @@ export class WazuhApiCtrl { log('wazuh-api:checkStoredAPI', `${id} exists`, 'debug'); // 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 responseManagerInfo = + await context.wazuh.api.client.asInternalUser.request( + 'get', + `/manager/info`, + {}, + { apiHostID: id, forceRefresh: true }, + ); // Look for socket-related errors if (this.checkResponseIsDown(responseManagerInfo)) { return ErrorResponse( - `ERROR3099 - ${responseManagerInfo.data.detail || 'Wazuh not ready yet'}`, + `ERROR3099 - ${ + responseManagerInfo.data.detail || 'Wazuh not ready yet' + }`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, - response + response, ); } // If we have a valid response from the Wazuh API - if (responseManagerInfo.status === HTTP_STATUS_CODES.OK && responseManagerInfo.data) { + if ( + responseManagerInfo.status === HTTP_STATUS_CODES.OK && + responseManagerInfo.data + ) { // Clear and update cluster information before being sent back to frontend delete api.cluster_info; - const responseAgents = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/agents`, - { params: { agents_list: '000' } }, - { apiHostID: id } - ); - - if (responseAgents.status === HTTP_STATUS_CODES.OK) { - const managerName = responseAgents.data.data.affected_items[0].manager; - - const responseClusterStatus = await context.wazuh.api.client.asInternalUser.request( + const responseAgents = + await context.wazuh.api.client.asInternalUser.request( 'GET', - `/cluster/status`, - {}, - { apiHostID: id } + `/agents`, + { params: { agents_list: '000' } }, + { apiHostID: id }, ); + + if (responseAgents.status === HTTP_STATUS_CODES.OK) { + const managerName = + responseAgents.data.data.affected_items[0].manager; + + const responseClusterStatus = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/cluster/status`, + {}, + { apiHostID: id }, + ); if (responseClusterStatus.status === HTTP_STATUS_CODES.OK) { if (responseClusterStatus.data.data.enabled === 'yes') { - const responseClusterLocalInfo = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/cluster/local/info`, - {}, - { apiHostID: id } - ); + const responseClusterLocalInfo = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/cluster/local/info`, + {}, + { apiHostID: id }, + ); if (responseClusterLocalInfo.status === HTTP_STATUS_CODES.OK) { - const clusterEnabled = responseClusterStatus.data.data.enabled === 'yes'; + const clusterEnabled = + responseClusterStatus.data.data.enabled === 'yes'; api.cluster_info = { status: clusterEnabled ? 'enabled' : 'disabled', manager: managerName, - node: responseClusterLocalInfo.data.data.affected_items[0].node, + node: responseClusterLocalInfo.data.data.affected_items[0] + .node, cluster: clusterEnabled - ? responseClusterLocalInfo.data.data.affected_items[0].cluster + ? responseClusterLocalInfo.data.data.affected_items[0] + .cluster : 'Disabled', }; } @@ -200,28 +252,31 @@ export class WazuhApiCtrl { statusCode: HTTP_STATUS_CODES.OK, data: copied, idChanged: request.body.idChanged || null, - } + }, }); } } } // If we have an invalid response from the Wazuh API - throw new Error(responseManagerInfo.data.detail || `${api.url}:${api.port} is unreachable`); + throw new Error( + responseManagerInfo.data.detail || + `${api.url}:${api.port} is unreachable`, + ); } catch (error) { if (error.code === 'EPROTO') { return response.ok({ body: { statusCode: HTTP_STATUS_CODES.OK, data: { apiIsDown: true }, - } + }, }); } else if (error.code === 'ECONNREFUSED') { return response.ok({ body: { statusCode: HTTP_STATUS_CODES.OK, data: { apiIsDown: true }, - } + }, }); } else { try { @@ -230,19 +285,22 @@ export class WazuhApiCtrl { try { const id = Object.keys(api)[0]; - const responseManagerInfo = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/manager/info`, - {}, - { apiHostID: id } - ); + const responseManagerInfo = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/manager/info`, + {}, + { apiHostID: id }, + ); if (this.checkResponseIsDown(responseManagerInfo)) { return ErrorResponse( - `ERROR3099 - ${response.data.detail || 'Wazuh not ready yet'}`, + `ERROR3099 - ${ + response.data.detail || 'Wazuh not ready yet' + }`, 3099, HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, - response + response, ); } if (responseManagerInfo.status === HTTP_STATUS_CODES.OK) { @@ -250,7 +308,7 @@ export class WazuhApiCtrl { request.body.idChanged = id; return await this.checkStoredAPI(context, request, response); } - } catch (error) { } // eslint-disable-line + } catch (error) {} // eslint-disable-line } } catch (error) { log('wazuh-api:checkStoredAPI', error.message || error); @@ -258,7 +316,7 @@ export class WazuhApiCtrl { error.message || error, 3020, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } log('wazuh-api:checkStoredAPI', error.message || error); @@ -266,7 +324,7 @@ export class WazuhApiCtrl { error.message || error, 3002, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -307,7 +365,11 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} status obj or ErrorResponse */ - async checkAPI(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async checkAPI( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { let apiAvailable = null; // const notValid = this.validateCheckApiParams(request.body); @@ -323,95 +385,118 @@ export class WazuhApiCtrl { `The API ${request.body.id} was not found`, 3029, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } const options = { apiHostID: request.body.id }; if (request.body.forceRefresh) { - options["forceRefresh"] = request.body.forceRefresh; + options['forceRefresh'] = request.body.forceRefresh; } let responseManagerInfo; - try{ - responseManagerInfo = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/manager/info`, - {}, - options - ); - }catch(error){ + try { + responseManagerInfo = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/manager/info`, + {}, + options, + ); + } catch (error) { return ErrorResponse( - `ERROR3099 - ${error.response?.data?.detail || 'Wazuh not ready yet'}`, + `ERROR3099 - ${ + error.response?.data?.detail || 'Wazuh not ready yet' + }`, 3099, error?.response?.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, - response + response, ); } - log('wazuh-api:checkAPI', `${request.body.id} credentials are valid`, 'debug'); - if (responseManagerInfo.status === HTTP_STATUS_CODES.OK && responseManagerInfo.data) { - let responseAgents = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/agents`, - { params: { agents_list: '000' } }, - { apiHostID: request.body.id } - ); - - if (responseAgents.status === HTTP_STATUS_CODES.OK) { - const managerName = responseAgents.data.data.affected_items[0].manager; - - let responseCluster = await context.wazuh.api.client.asInternalUser.request( + log( + 'wazuh-api:checkAPI', + `${request.body.id} credentials are valid`, + 'debug', + ); + if ( + responseManagerInfo.status === HTTP_STATUS_CODES.OK && + responseManagerInfo.data + ) { + let responseAgents = + await context.wazuh.api.client.asInternalUser.request( 'GET', - `/cluster/status`, - {}, - { apiHostID: request.body.id } + `/agents`, + { params: { agents_list: '000' } }, + { apiHostID: request.body.id }, ); + if (responseAgents.status === HTTP_STATUS_CODES.OK) { + const managerName = + responseAgents.data.data.affected_items[0].manager; + + let responseCluster = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/cluster/status`, + {}, + { apiHostID: request.body.id }, + ); + // Check the run_as for the API user and update it let apiUserAllowRunAs = API_USER_STATUS_RUN_AS.ALL_DISABLED; - const responseApiUserAllowRunAs = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/security/users/me`, - {}, - { apiHostID: request.body.id } - ); + const responseApiUserAllowRunAs = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/security/users/me`, + {}, + { apiHostID: request.body.id }, + ); if (responseApiUserAllowRunAs.status === HTTP_STATUS_CODES.OK) { - const allow_run_as = responseApiUserAllowRunAs.data.data.affected_items[0].allow_run_as; + const allow_run_as = + responseApiUserAllowRunAs.data.data.affected_items[0] + .allow_run_as; - if (allow_run_as && apiAvailable && apiAvailable.run_as) // HOST AND USER ENABLED + if (allow_run_as && apiAvailable && apiAvailable.run_as) + // HOST AND USER ENABLED apiUserAllowRunAs = API_USER_STATUS_RUN_AS.ENABLED; - - else if (!allow_run_as && apiAvailable && apiAvailable.run_as)// HOST ENABLED AND USER DISABLED + else if (!allow_run_as && apiAvailable && apiAvailable.run_as) + // HOST ENABLED AND USER DISABLED apiUserAllowRunAs = API_USER_STATUS_RUN_AS.USER_NOT_ALLOWED; - - else if (allow_run_as && ( !apiAvailable || !apiAvailable.run_as )) // USER ENABLED AND HOST DISABLED + else if (allow_run_as && (!apiAvailable || !apiAvailable.run_as)) + // USER ENABLED AND HOST DISABLED apiUserAllowRunAs = API_USER_STATUS_RUN_AS.HOST_DISABLED; - - else if (!allow_run_as && ( !apiAvailable || !apiAvailable.run_as )) // HOST AND USER DISABLED + else if (!allow_run_as && (!apiAvailable || !apiAvailable.run_as)) + // HOST AND USER DISABLED apiUserAllowRunAs = API_USER_STATUS_RUN_AS.ALL_DISABLED; } CacheInMemoryAPIUserAllowRunAs.set( request.body.id, apiAvailable.username, - apiUserAllowRunAs + apiUserAllowRunAs, ); if (responseCluster.status === HTTP_STATUS_CODES.OK) { - log('wazuh-api:checkStoredAPI', `Wazuh API response is valid`, 'debug'); + log( + 'wazuh-api:checkStoredAPI', + `Wazuh API response is valid`, + 'debug', + ); if (responseCluster.data.data.enabled === 'yes') { // If cluster mode is active - let responseClusterLocal = await context.wazuh.api.client.asInternalUser.request( - 'GET', - `/cluster/local/info`, - {}, - { apiHostID: request.body.id } - ); + let responseClusterLocal = + await context.wazuh.api.client.asInternalUser.request( + 'GET', + `/cluster/local/info`, + {}, + { apiHostID: request.body.id }, + ); if (responseClusterLocal.status === HTTP_STATUS_CODES.OK) { return response.ok({ body: { manager: managerName, node: responseClusterLocal.data.data.affected_items[0].node, - cluster: responseClusterLocal.data.data.affected_items[0].cluster, + cluster: + responseClusterLocal.data.data.affected_items[0].cluster, status: 'enabled', allow_run_as: apiUserAllowRunAs, }, @@ -434,20 +519,29 @@ export class WazuhApiCtrl { } catch (error) { log('wazuh-api:checkAPI', error.message || error); - if (error && error.response && error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED) { + if ( + error && + error.response && + error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED + ) { return ErrorResponse( `Unathorized. Please check API credentials. ${error.response.data.message}`, HTTP_STATUS_CODES.UNAUTHORIZED, HTTP_STATUS_CODES.UNAUTHORIZED, - response + response, ); } - if (error && error.response && error.response.data && error.response.data.detail) { + if ( + error && + error.response && + error.response.data && + error.response.data.detail + ) { return ErrorResponse( error.response.data.detail, error.response.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, error.response.status || HTTP_STATUS_CODES.SERVICE_UNAVAILABLE, - response + response, ); } if (error.code === 'EPROTO') { @@ -455,14 +549,14 @@ export class WazuhApiCtrl { 'Wrong protocol being used to connect to the Wazuh API', 3005, HTTP_STATUS_CODES.BAD_REQUEST, - response + response, ); } return ErrorResponse( error.message || error, 3005, error?.response?.status || HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -471,10 +565,14 @@ 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 && log('wazuh-api:makeRequest', 'Wazuh API is online but Wazuh is not ready yet'); + isDown && + log( + 'wazuh-api:makeRequest', + 'Wazuh API is online but Wazuh is not ready yet', + ); return isDown; } @@ -493,10 +591,12 @@ export class WazuhApiCtrl { 'GET', '/manager/status', {}, - { apiHostID: api.id } + { 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' && @@ -506,7 +606,9 @@ export class WazuhApiCtrl { const execd = daemons['wazuh-execd'] === 'running'; const modulesd = daemons['wazuh-modulesd'] === 'running'; const wazuhdb = wazuhdbExists ? daemons['wazuh-db'] === 'running' : true; - const clusterd = isCluster ? daemons['wazuh-clusterd'] === 'running' : true; + const clusterd = isCluster + ? daemons['wazuh-clusterd'] === 'running' + : true; const isValid = execd && modulesd && wazuhdb && clusterd; @@ -544,8 +646,10 @@ export class WazuhApiCtrl { shouldKeepArrayAsIt(method, path) { // Methods that we must respect a do not transform them const isAgentsRestart = method === 'POST' && path === '/agents/restart'; - const isActiveResponse = method === 'PUT' && path.startsWith('/active-response'); - const isAddingAgentsToGroup = method === 'POST' && path.startsWith('/agents/group/'); + const isActiveResponse = + method === 'PUT' && path.startsWith('/active-response'); + const isAddingAgentsToGroup = + method === 'POST' && path.startsWith('/agents/group/'); // Returns true only if one of the above conditions is true return isAgentsRestart || isActiveResponse || isAddingAgentsToGroup; @@ -561,7 +665,6 @@ export class WazuhApiCtrl { * @returns {Object} API response or ErrorResponse */ async makeRequest(context, method, path, data, id, response) { - const devTools = !!(data || {}).devTools; try { const api = await this.manageHosts.getHostById(id); @@ -572,33 +675,47 @@ export class WazuhApiCtrl { if (!Object.keys(api).length) { log('wazuh-api:makeRequest', 'Could not get host credentials'); //Can not get credentials from wazuh-hosts - return ErrorResponse('Could not get host credentials', 3011, HTTP_STATUS_CODES.NOT_FOUND, response); + return ErrorResponse( + 'Could not get host credentials', + 3011, + HTTP_STATUS_CODES.NOT_FOUND, + response, + ); } if (!data) { data = {}; - }; + } if (!data.headers) { data.headers = {}; - }; + } const options = { - apiHostID: id + apiHostID: id, }; // 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; } @@ -607,15 +724,25 @@ export class WazuhApiCtrl { addJobToQueue({ startAt: new Date(Date.now() + delay), run: async () => { - try{ - await context.wazuh.api.client.asCurrentUser.request(method, path, data, options); - }catch(error){ - log('queue:delayApiRequest',`An error ocurred in the delayed request: "${method} ${path}": ${error.message || error}`); - }; - } + try { + await context.wazuh.api.client.asCurrentUser.request( + method, + path, + data, + options, + ); + } catch (error) { + log( + 'queue:delayApiRequest', + `An error ocurred in the delayed request: "${method} ${path}": ${ + error.message || error + }`, + ); + } + }, }); return response.ok({ - body: { error: 0, message: 'Success' } + body: { error: 0, message: 'Success' }, }); } @@ -626,12 +753,15 @@ export class WazuhApiCtrl { } catch (error) { const isDown = (error || {}).code === 'ECONNREFUSED'; if (!isDown) { - log('wazuh-api:makeRequest', 'Wazuh API is online but Wazuh is not ready yet'); + log( + 'wazuh-api:makeRequest', + 'Wazuh API is online but Wazuh is not ready yet', + ); return ErrorResponse( `ERROR3099 - ${error.message || 'Wazuh not ready yet'}`, 3099, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -653,55 +783,68 @@ export class WazuhApiCtrl { } } - const responseToken = await context.wazuh.api.client.asCurrentUser.request(method, path, data, options); + const responseToken = + await context.wazuh.api.client.asCurrentUser.request( + method, + path, + data, + options, + ); const responseIsDown = this.checkResponseIsDown(responseToken); if (responseIsDown) { return ErrorResponse( `ERROR3099 - ${response.body.message || 'Wazuh not ready yet'}`, 3099, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } let responseBody = (responseToken || {}).data || {}; if (!responseBody) { responseBody = - typeof responseBody === 'string' && path.includes('/files') && method === 'GET' + typeof responseBody === 'string' && + path.includes('/files') && + method === 'GET' ? ' ' : false; response.data = responseBody; } - const responseError = response.status !== HTTP_STATUS_CODES.OK ? response.status : false; + const responseError = + response.status !== HTTP_STATUS_CODES.OK ? response.status : false; if (!responseError && responseBody) { //cleanKeys(response); return response.ok({ - body: responseToken.data + body: responseToken.data, }); } if (responseError && devTools) { return response.ok({ - body: response.data + body: response.data, }); } throw responseError && responseBody.detail ? { message: responseBody.detail, code: responseError } : new Error('Unexpected error fetching data from the Wazuh API'); } catch (error) { - if (error && error.response && error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED) { + if ( + error && + error.response && + error.response.status === HTTP_STATUS_CODES.UNAUTHORIZED + ) { return ErrorResponse( error.message || error, error.code ? `Wazuh API error: ${error.code}` : 3013, HTTP_STATUS_CODES.UNAUTHORIZED, - response + response, ); } - const errorMsg = (error.response || {}).data || error.message + const errorMsg = (error.response || {}).data || error.message; log('wazuh-api:makeRequest', errorMsg || error); if (devTools) { return response.ok({ - body: { error: '3013', message: errorMsg || error } + body: { error: '3013', message: errorMsg || error }, }); } else { if ((error || {}).code && ApiErrorEquivalence[error.code]) { @@ -711,7 +854,7 @@ export class WazuhApiCtrl { errorMsg.detail || error, error.code ? `Wazuh API error: ${error.code}` : 3013, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -724,38 +867,61 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} api response or ErrorResponse */ - requestApi(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { - + requestApi( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { const idApi = getCookieValueByName(request.headers.cookie, 'wz-api'); - if (idApi !== request.body.id) { // if the current token belongs to a different API id, we relogin to obtain a new token + if (idApi !== request.body.id) { + // if the current token belongs to a different API id, we relogin to obtain a new token return ErrorResponse( 'status code 401', HTTP_STATUS_CODES.UNAUTHORIZED, HTTP_STATUS_CODES.UNAUTHORIZED, - response + response, ); } if (!request.body.method) { - return ErrorResponse('Missing param: method', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response); + return ErrorResponse( + 'Missing param: method', + 3015, + HTTP_STATUS_CODES.BAD_REQUEST, + response, + ); } else if (!request.body.method.match(/^(?:GET|PUT|POST|DELETE)$/)) { log('wazuh-api:makeRequest', 'Request method is not valid.'); //Method is not a valid HTTP request method - return ErrorResponse('Request method is not valid.', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response); + return ErrorResponse( + 'Request method is not valid.', + 3015, + HTTP_STATUS_CODES.BAD_REQUEST, + response, + ); } else if (!request.body.path) { - return ErrorResponse('Missing param: path', 3016, HTTP_STATUS_CODES.BAD_REQUEST, response); + return ErrorResponse( + 'Missing param: path', + 3016, + HTTP_STATUS_CODES.BAD_REQUEST, + response, + ); } else if (!request.body.path.startsWith('/')) { log('wazuh-api:makeRequest', 'Request path is not valid.'); //Path doesn't start with '/' - return ErrorResponse('Request path is not valid.', 3015, HTTP_STATUS_CODES.BAD_REQUEST, response); + return ErrorResponse( + 'Request path is not valid.', + 3015, + HTTP_STATUS_CODES.BAD_REQUEST, + response, + ); } else { - return this.makeRequest( context, request.body.method, request.body.path, request.body.body, request.body.id, - response + response, ); } } @@ -767,12 +933,19 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} csv or ErrorResponse */ - async csv(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async csv( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { - if (!request.body || !request.body.path) throw new Error('Field path is required'); + if (!request.body || !request.body.path) + 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) ? request.body.filters : []; + const filters = Array.isArray(((request || {}).body || {}).filters) + ? request.body.filters + : []; let tmpPath = request.body.path; @@ -799,12 +972,17 @@ export class WazuhApiCtrl { 'GET', `/${tmpPath}`, { params: params }, - { apiHostID: request.body.id } + { apiHostID: request.body.id }, ); - const isList = request.body.path.includes('/lists') && request.body.filters && request.body.filters.length && request.body.filters.find(filter => filter._isCDBList); + const isList = + request.body.path.includes('/lists') && + request.body.filters && + 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; @@ -815,7 +993,7 @@ export class WazuhApiCtrl { 'GET', `/${tmpPath}`, { params: params }, - { apiHostID: request.body.id } + { apiHostID: request.body.id }, ); itemsArray.push(...tmpData.data.data.affected_items); } @@ -823,8 +1001,7 @@ export class WazuhApiCtrl { if (totalItems) { const { path, filters } = request.body; - const isArrayOfLists = - path.includes('/lists') && !isList; + const isArrayOfLists = path.includes('/lists') && !isList; const isAgents = path.includes('/agents') && !path.includes('groups'); const isAgentsOfGroup = path.startsWith('/agents/groups/'); const isFiles = path.endsWith('/files'); @@ -862,7 +1039,13 @@ export class WazuhApiCtrl { const flatLists = []; for (const list of itemsArray) { const { relative_dirname, items } = list; - flatLists.push(...items.map(item => ({ relative_dirname, key: item.key, value: item.value }))); + flatLists.push( + ...items.map(item => ({ + relative_dirname, + key: item.key, + value: item.value, + })), + ); } fields = ['relative_dirname', 'key', 'value']; itemsArray = [...flatLists]; @@ -886,24 +1069,44 @@ export class WazuhApiCtrl { return response.ok({ headers: { 'Content-Type': 'text/csv' }, - body: csv + body: csv, }); - } else if (output && output.data && output.data.data && !output.data.data.total_affected_items) { + } else if ( + output && + output.data && + output.data.data && + !output.data.data.total_affected_items + ) { throw new Error('No results'); } else { - throw new Error(`An error occurred fetching data from the Wazuh API${output && output.data && output.data.detail ? `: ${output.body.detail}` : ''}`); + throw new Error( + `An error occurred fetching data from the Wazuh API${ + output && output.data && output.data.detail + ? `: ${output.body.detail}` + : '' + }`, + ); } } catch (error) { log('wazuh-api:csv', error.message || error); - return ErrorResponse(error.message || error, 3034, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response); + return ErrorResponse( + error.message || error, + 3034, + HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, + response, + ); } } // Get de list of available requests in the API - getRequestList(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + getRequestList( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { //Read a static JSON until the api call has implemented return response.ok({ - body: apiRequestList + body: apiRequestList, }); } @@ -914,20 +1117,26 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} timestamp field or ErrorResponse */ - getTimeStamp(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + getTimeStamp( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { - const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8')); + const source = JSON.parse( + fs.readFileSync(this.updateRegistry.file, 'utf8'), + ); if (source.installationDate && source.lastRestart) { log( 'wazuh-api:getTimeStamp', `Installation date: ${source.installationDate}. Last restart: ${source.lastRestart}`, - 'debug' + 'debug', ); return response.ok({ body: { installationDate: source.installationDate, lastRestart: source.lastRestart, - } + }, }); } else { throw new Error('Could not fetch wazuh-version registry'); @@ -938,7 +1147,7 @@ export class WazuhApiCtrl { error.message || 'Could not fetch wazuh-version registry', 4001, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -950,15 +1159,19 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} extensions object or ErrorResponse */ - async setExtensions(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async setExtensions( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { const { id, extensions } = request.body; // Update cluster information in the wazuh-registry.json await this.updateRegistry.updateAPIExtensions(id, extensions); return response.ok({ body: { - statusCode: HTTP_STATUS_CODES.OK - } + statusCode: HTTP_STATUS_CODES.OK, + }, }); } catch (error) { log('wazuh-api:setExtensions', error.message || error); @@ -966,7 +1179,7 @@ export class WazuhApiCtrl { error.message || 'Could not set extensions', 4001, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -978,15 +1191,19 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} extensions object or ErrorResponse */ - getExtensions(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + getExtensions( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { const source = JSON.parse( - fs.readFileSync(this.updateRegistry.file, 'utf8') + fs.readFileSync(this.updateRegistry.file, 'utf8'), ); return response.ok({ body: { - extensions: (source.hosts[request.params.id] || {}).extensions || {} - } + extensions: (source.hosts[request.params.id] || {}).extensions || {}, + }, }); } catch (error) { log('wazuh-api:getExtensions', error.message || error); @@ -994,7 +1211,7 @@ export class WazuhApiCtrl { error.message || 'Could not fetch wazuh-version registry', 4001, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -1006,22 +1223,30 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} setup info or ErrorResponse */ - async getSetupInfo(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async getSetupInfo( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { - const source = JSON.parse(fs.readFileSync(this.updateRegistry.file, 'utf8')); + const source = JSON.parse( + fs.readFileSync(this.updateRegistry.file, 'utf8'), + ); return response.ok({ body: { statusCode: HTTP_STATUS_CODES.OK, - data: !Object.values(source).length ? '' : source - } + data: !Object.values(source).length ? '' : source, + }, }); } catch (error) { log('wazuh-api:getSetupInfo', error.message || error); return ErrorResponse( - `Could not get data from wazuh-version registry due to ${error.message || error}`, + `Could not get data from wazuh-version registry due to ${ + error.message || error + }`, 4005, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, - response + response, ); } } @@ -1033,9 +1258,13 @@ export class WazuhApiCtrl { * @param {Object} response * @returns {Object} Basic syscollector information */ - async getSyscollector(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async getSyscollector( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { - const apiHostID = getCookieValueByName(request.headers.cookie,'wz-api'); + const apiHostID = getCookieValueByName(request.headers.cookie, 'wz-api'); if (!request.params || !apiHostID || !request.params.agent) { throw new Error('Agent ID and API ID are required'); } @@ -1043,8 +1272,18 @@ export class WazuhApiCtrl { const { agent } = request.params; const data = await Promise.all([ - context.wazuh.api.client.asInternalUser.request('GET', `/syscollector/${agent}/hardware`, {}, { apiHostID }), - context.wazuh.api.client.asInternalUser.request('GET', `/syscollector/${agent}/os`, {}, { apiHostID }) + context.wazuh.api.client.asInternalUser.request( + 'GET', + `/syscollector/${agent}/hardware`, + {}, + { apiHostID }, + ), + context.wazuh.api.client.asInternalUser.request( + 'GET', + `/syscollector/${agent}/os`, + {}, + { apiHostID }, + ), ]); const result = data.map(item => (item.data || {}).data || []); @@ -1053,7 +1292,8 @@ export class WazuhApiCtrl { // Fill syscollector object const syscollector = { hardware: - typeof hardwareResponse === 'object' && Object.keys(hardwareResponse).length + typeof hardwareResponse === 'object' && + Object.keys(hardwareResponse).length ? { ...hardwareResponse.affected_items[0] } : false, os: @@ -1063,11 +1303,16 @@ export class WazuhApiCtrl { }; return response.ok({ - body: syscollector + body: syscollector, }); } catch (error) { log('wazuh-api:getSyscollector', error.message || error); - return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response); + return ErrorResponse( + error.message || error, + 3035, + HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, + response, + ); } } /** @@ -1077,23 +1322,36 @@ export class WazuhApiCtrl { * @param response * @returns {object} Returns { isWazuhDisabled: boolean parsed integer } */ - async isWazuhDisabled(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async isWazuhDisabled( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { - - const disabledRoles = ( await getConfiguration() )['disabled_roles'] || []; - const logoSidebar = ( await getConfiguration() )['customization.logo.sidebar']; - const data = (await context.wazuh.security.getCurrentUser(request, context)).authContext; - - const isWazuhDisabled = +(data.roles || []).some((role) => disabledRoles.includes(role)); + const disabledRoles = (await getConfiguration())['disabled_roles'] || []; + const logoSidebar = (await getConfiguration())[ + 'customization.logo.sidebar' + ]; + const data = ( + await context.wazuh.security.getCurrentUser(request, context) + ).authContext; + + const isWazuhDisabled = +(data.roles || []).some(role => + disabledRoles.includes(role), + ); return response.ok({ - body: { isWazuhDisabled, logoSidebar } + body: { isWazuhDisabled, logoSidebar }, }); } catch (error) { log('wazuh-api:isWazuhDisabled', error.message || error); - return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response); + return ErrorResponse( + error.message || error, + 3035, + HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, + response, + ); } - } /** @@ -1102,26 +1360,37 @@ export class WazuhApiCtrl { * @param request * @param response */ - async getAppLogos(context: RequestHandlerContext, request: OpenSearchDashboardsRequest, response: OpenSearchDashboardsResponseFactory) { + async getAppLogos( + context: RequestHandlerContext, + request: OpenSearchDashboardsRequest, + response: OpenSearchDashboardsResponseFactory, + ) { try { const configuration = getConfiguration(); const SIDEBAR_LOGO = 'customization.logo.sidebar'; const APP_LOGO = 'customization.logo.app'; const HEALTHCHECK_LOGO = 'customization.logo.healthcheck'; - const logos= { + const logos = { [SIDEBAR_LOGO]: getCustomizationSetting(configuration, SIDEBAR_LOGO), [APP_LOGO]: getCustomizationSetting(configuration, APP_LOGO), - [HEALTHCHECK_LOGO]: getCustomizationSetting(configuration, HEALTHCHECK_LOGO), - } + [HEALTHCHECK_LOGO]: getCustomizationSetting( + configuration, + HEALTHCHECK_LOGO, + ), + }; return response.ok({ - body: { logos } + body: { logos }, }); } catch (error) { log('wazuh-api:getAppLogos', error.message || error); - return ErrorResponse(error.message || error, 3035, HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, response); + return ErrorResponse( + error.message || error, + 3035, + HTTP_STATUS_CODES.INTERNAL_SERVER_ERROR, + response, + ); } - } } From 3363bff5e05b2589992f4c82297b0f51f52856de Mon Sep 17 00:00:00 2001 From: Tostti Date: Mon, 30 Oct 2023 12:46:37 -0300 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index febbc29bca..429056fd00 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ All notable changes to the Wazuh app project will be documented in this file. - Support for Wazuh 4.7.1 +### Fixed + +- Fixed problem when using chinese characters in the username [#6076](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6076) + ## Wazuh v4.7.0 - OpenSearch Dashboards 2.8.0 - Revision 01 ### Added @@ -35,7 +39,6 @@ All notable changes to the Wazuh app project will be documented in this file. ## Wazuh v4.6.0 - OpenSearch Dashboards 2.8.0 - Revision 03 - ### Added - Added rel="noopener noreferrer" in documentation links. [#5197](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5197) [#5274](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5274) [#5298](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5298) [#5409](https://github.com/wazuh/wazuh-dashboard-plugins/pull/5409) From 0382b54792a14fed97b1a14319e2506231767657 Mon Sep 17 00:00:00 2001 From: Tostti Date: Mon, 30 Oct 2023 14:10:36 -0300 Subject: [PATCH 3/3] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 429056fd00..bbe95910d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,7 +10,7 @@ All notable changes to the Wazuh app project will be documented in this file. ### Fixed -- Fixed problem when using chinese characters in the username [#6076](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6076) +- Fixed problem when using non latin characters in the username [#6076](https://github.com/wazuh/wazuh-dashboard-plugins/pull/6076) ## Wazuh v4.7.0 - OpenSearch Dashboards 2.8.0 - Revision 01