From 94d0a83e43aa1d2d84ef6f87cbb76b9aefa085b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20=C3=81ngel?= Date: Mon, 10 Jun 2019 10:29:17 +0200 Subject: [PATCH] Improved error checking + syscollector performance --- public/controllers/agent/agents.js | 6 +- .../components/inventory-interfaces-table.js | 100 ----------- public/controllers/agent/index.js | 4 +- .../wz-table-eui/wz-table-directive.js | 27 ++- .../templates/agents/agents-syscollector.html | 49 ++---- server/controllers/wazuh-api.js | 164 +++++++----------- 6 files changed, 105 insertions(+), 245 deletions(-) delete mode 100644 public/controllers/agent/components/inventory-interfaces-table.js diff --git a/public/controllers/agent/agents.js b/public/controllers/agent/agents.js index 6e570c40c..627c8fbda 100644 --- a/public/controllers/agent/agents.js +++ b/public/controllers/agent/agents.js @@ -780,13 +780,13 @@ export class AgentsController { * @param {String} binding_text * @param {String} date */ - offsetTimestamp = (text, time) => { + offsetTimestamp(text, time) { try { return text + this.timeService.offset(time); } catch (error) { - return `${text}${time} (UTC)`; + return time !== '-' ? `${text}${time} (UTC)` : time; } - }; + } /** * Navigate to the groups of an agent diff --git a/public/controllers/agent/components/inventory-interfaces-table.js b/public/controllers/agent/components/inventory-interfaces-table.js deleted file mode 100644 index d67b33487..000000000 --- a/public/controllers/agent/components/inventory-interfaces-table.js +++ /dev/null @@ -1,100 +0,0 @@ -import React, { Component } from 'react'; -import PropTypes from 'prop-types'; -import { EuiBasicTable, EuiHealth } from '@elastic/eui'; - -export class InventoryInterfacesTable extends Component { - constructor(props) { - super(props); - - this.state = { - items: this.props.items, - pageIndex: 0, - pageSize: 10 - }; - } - - UNSAFE_componentWillReceiveProps(nextProps) { - this.setState({ - items: nextProps.items - }); - } - - onTableChange({ page = {} }) { - const { index: pageIndex, size: pageSize } = page; - - this.setState({ - pageIndex, - pageSize - }); - } - - filterItems(pageIndex, pageSize) { - const { items } = this.state; - const pages = []; - const len = items.length; - for (let i = 0, j = len; i < j; i += pageSize) { - pages.push(items.slice(i, i + pageSize)); - } - return { pageOfItems: pages[pageIndex] || [], totalItemCount: len }; - } - - render() { - const { pageIndex, pageSize } = this.state; - - const { pageOfItems, totalItemCount } = this.filterItems( - pageIndex, - pageSize - ); - - const columns = [ - { - field: 'name', - name: 'Name' - }, - { - field: 'mac', - name: 'MAC' - }, - { - field: 'state', - name: 'State', - render: state => ( - - {state} - - ) - }, - { - field: 'mtu', - name: 'MTU' - }, - { - field: 'type', - name: 'Type' - } - ]; - - const pagination = { - pageIndex, - pageSize, - totalItemCount, - pageSizeOptions: [10, 20, 50], - hidePerPageOptions: this.state.items.length <= 10 - }; - - return ( -
- this.onTableChange(obj)} - /> -
- ); - } -} - -InventoryInterfacesTable.propTypes = { - items: PropTypes.array -}; diff --git a/public/controllers/agent/index.js b/public/controllers/agent/index.js index 34db5f835..4ba6b31f0 100644 --- a/public/controllers/agent/index.js +++ b/public/controllers/agent/index.js @@ -14,7 +14,6 @@ import { AgentsPreviewController } from './agents-preview'; import { AgentsController } from './agents'; import { WelcomeScreen } from './components/welcome'; import { Stats } from './components/stats'; -import { InventoryInterfacesTable } from './components/inventory-interfaces-table'; const app = uiModules.get('app/wazuh', []); @@ -22,5 +21,4 @@ app .controller('agentsController', AgentsController) .controller('agentsPreviewController', AgentsPreviewController) .value('WelcomeScreenAgent', WelcomeScreen) - .value('StatsAgent', Stats) - .value('InventoryInterfacesTable', InventoryInterfacesTable); + .value('StatsAgent', Stats); diff --git a/public/directives/wz-table-eui/wz-table-directive.js b/public/directives/wz-table-eui/wz-table-directive.js index 7bb51d8ac..2443db84b 100644 --- a/public/directives/wz-table-eui/wz-table-directive.js +++ b/public/directives/wz-table-eui/wz-table-directive.js @@ -18,6 +18,8 @@ import * as listeners from './lib/listeners'; import { searchData, filterData, queryData } from './lib/data'; import { initTable } from './lib/init'; import { sort } from './lib/sort'; +import React, { Component } from 'react'; +import { EuiHealth } from '@elastic/eui'; const app = uiModules.get('app/wazuh', []); @@ -29,7 +31,14 @@ app.directive('wzTableEui', function() { keys: '=keys', initialSortField: '=initialSortField' }, - controller($scope, apiReq, errorHandler, wzTableFilter) { + controller($scope, apiReq, errorHandler, wzTableFilter, timeService) { + const health = (state, config) => ( + + {state} + + ); + + const defaultRender = value => value || '-'; const parseColumns = columnsArray => { return columnsArray.map(item => ({ @@ -37,7 +46,8 @@ app.directive('wzTableEui', function() { field: item.value || item, width: item.width || undefined, sortable: typeof item.sortable !== 'undefined' ? item.sortable : true, - render: value => value || '-' + render: value => + item.isHealth ? health(value, item.isHealth) : defaultRender(value) })); }; @@ -63,12 +73,23 @@ app.directive('wzTableEui', function() { } }; + const offsetTimestamp = (text, time) => { + try { + return text + timeService.offset(time); + } catch (error) { + return time !== '-' ? `${text}${time} (UTC)` : time; + } + }; + $scope.basicTableProps = { + path: $scope.path, initialSortField: $scope.initialSortField || false, columns: parseColumns($scope.keys), items: [], getData: options => fetch(options), - sortByField: field => sort(field, $scope, instance, fetch, errorHandler) + sortByField: field => + sort(field, $scope, instance, fetch, errorHandler), + offsetTimestamp: (text, time) => offsetTimestamp(text, time) //noItemsMessage: 'Change this' }; diff --git a/public/templates/agents/agents-syscollector.html b/public/templates/agents/agents-syscollector.html index 756d93620..d898856a2 100644 --- a/public/templates/agents/agents-syscollector.html +++ b/public/templates/agents/agents-syscollector.html @@ -54,40 +54,31 @@
- - No network - interfaces information available - - + - Network interfaces - + Network interfaces + - - + + + - - No network - ports information available - - + - Network ports - + Network ports + + path="'/syscollector/' + agent.id + '/ports'" initial-sort-field="'process'" + keys="['process',{value:'local.ip', sortable:false},{value:'local.port', sortable:false},'state','protocol']"> + keys="[{value:'local.ip', sortable:false},{value:'local.port', sortable:false}','state','protocol']"> @@ -95,12 +86,7 @@
- - No network - addresses information available - - + Network settings @@ -115,9 +101,8 @@ - Packages - + Packages +
@@ -164,8 +149,6 @@ Processes -
diff --git a/server/controllers/wazuh-api.js b/server/controllers/wazuh-api.js index 2ff2bef8b..45087cacf 100644 --- a/server/controllers/wazuh-api.js +++ b/server/controllers/wazuh-api.js @@ -57,13 +57,7 @@ export class WazuhApiCtrl { ); } log('wazuh-api:checkStoredAPI', `${req.payload} exists`, 'debug'); - // Always check the daemons before requesting any endpoint - try { - await this.checkDaemons(api, null); - } catch (error) { - const isDown = (error || {}).code === 'ECONNREFUSED'; - if (!isDown) return ErrorResponse('ERROR3099', 3099, 500, reply); - } + const credInfo = ApiHelper.buildOptionsObject(api); let response = await needle( @@ -73,6 +67,10 @@ export class WazuhApiCtrl { credInfo ); + if (this.checkResponseIsDown(response)) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + if (parseInt(response.body.error) === 0 && response.body.data) { // Checking the cluster status response = await needle( @@ -82,6 +80,10 @@ export class WazuhApiCtrl { credInfo ); + if (this.checkResponseIsDown(response)) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + if (!response.body.error) { try { const managerInfo = await needle( @@ -90,6 +92,11 @@ export class WazuhApiCtrl { {}, credInfo ); + + if (this.checkResponseIsDown(managerInfo)) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + const updatedManagerName = managerInfo.body.data.name; api.cluster_info.manager = updatedManagerName; await this.wzWrapper.updateWazuhIndexDocument(null, req.payload, { @@ -108,6 +115,10 @@ export class WazuhApiCtrl { credInfo ); + if (this.checkResponseIsDown(response)) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + if (!response.body.error) { let managerName = api.cluster_info.manager; delete api.cluster_info; @@ -195,6 +206,11 @@ export class WazuhApiCtrl { {}, options ); + + if (this.checkResponseIsDown(response)) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + if ( ((response || {}).body || {}).error === 0 && ((response || {}).body || {}).data @@ -561,6 +577,24 @@ export class WazuhApiCtrl { } } + checkResponseIsDown(response) { + const responseBody = (response || {}).body || {}; + const responseError = responseBody.error || false; + + // Avoid "Error communicating with socket" like errors + const socketErrorCodes = [1013, 1014, 1017, 1018, 1019]; + + const isDown = socketErrorCodes.includes(responseError || 1); + + isDown && + log( + 'wazuh-api:makeRequest', + 'Wazuh API is online but Wazuh is not ready yet' + ); + + return isDown; + } + /** * Check main Wazuh daemons status * @param {*} api API entry stored in .wazuh @@ -691,21 +725,19 @@ export class WazuhApiCtrl { return { error: 0, message: 'Success' }; } - // Always check the daemons before requesting any endpoint - try { - const check = await this.checkDaemons(api, path); - - if (path === '/ping') { + if (path === '/ping') { + try { + const check = await this.checkDaemons(api, path); return check; - } - } catch (error) { - const isDown = (error || {}).code === 'ECONNREFUSED'; - if (!isDown) { - log( - 'wazuh-api:makeRequest', - 'Wazuh API is online but Wazuh is not ready yet' - ); - return ErrorResponse('ERROR3099', 3099, 500, reply); + } catch (error) { + const isDown = (error || {}).code === 'ECONNREFUSED'; + if (!isDown) { + log( + 'wazuh-api:makeRequest', + 'Wazuh API is online but Wazuh is not ready yet' + ); + return ErrorResponse('ERROR3099', 3099, 500, reply); + } } } @@ -725,22 +757,16 @@ export class WazuhApiCtrl { options ); + const responseIsDown = this.checkResponseIsDown(response); + + if (responseIsDown) { + return ErrorResponse('ERROR3099', 3099, 500, reply); + } + const responseBody = (response || {}).body || {}; const responseData = responseBody.data || false; const responseError = responseBody.error || false; - // Avoid "1014 - Error communicating with socket" like errors - const socketErrorCodes = [1013, 1014, 1017, 1018, 1019]; - if (socketErrorCodes.includes(responseError || 1)) { - if (counter > 3) { - throw new Error( - `Tried to execute ${method} ${path} three times with no success, aborted.` - ); - } - await this.sleep(500); - return this.makeRequest(method, path, data, id, reply, counter + 1); - } - if (!responseError && responseData) { cleanKeys(response); return response.body; @@ -1203,74 +1229,15 @@ export class WazuhApiCtrl { `${config.url}:${config.port}/syscollector/${agent}/os`, {}, headers - ), - needle( - 'get', - `${config.url}:${config.port}/syscollector/${agent}/ports`, - { limit: 1 }, - headers - ), - needle( - 'get', - `${config.url}:${config.port}/syscollector/${agent}/packages`, - { - limit: 1, - select: 'scan_time' - }, - headers - ), - needle( - 'get', - `${config.url}:${config.port}/syscollector/${agent}/processes`, - { - limit: 1, - select: 'scan_time' - }, - headers ) ]); const result = data.map(item => (item.body || {}).data || false); const [ hardwareResponse, - osResponse, - portsResponse, - packagesDateResponse, - processesDateResponse + osResponse ] = result; - let netifaceResponse = false; - try { - const resultNetiface = await needle( - 'get', - `${config.url}:${config.port}/syscollector/${agent}/netiface`, - {}, - headers - ); - netifaceResponse = ((resultNetiface || {}).body || {}).data || false; - } catch (error) {} // eslint-disable-line - - // This API call may fail so we put it out of Promise.all - let netaddrResponse = false; - try { - const resultNetaddrResponse = await needle( - 'get', - `${config.url}:${config.port}/syscollector/${agent}/netaddr`, - { - limit: 1 - }, - headers - ); - netaddrResponse = - ((resultNetaddrResponse || {}).body || {}).data || false; - } catch (error) {} // eslint-disable-line - - const packagesDate = packagesDateResponse - ? { ...packagesDateResponse } - : false; - const processesDate = processesDateResponse - ? { ...processesDateResponse } - : false; // Fill syscollector object const syscollector = { @@ -1282,16 +1249,7 @@ export class WazuhApiCtrl { os: typeof osResponse === 'object' && Object.keys(osResponse).length ? { ...osResponse } - : false, - netiface: netifaceResponse ? { ...netifaceResponse } : false, - ports: portsResponse ? { ...portsResponse } : false, - netaddr: netaddrResponse ? { ...netaddrResponse } : false, - packagesDate: ((packagesDate || {}).items || []).length - ? packagesDate.items[0].scan_time - : '-', - processesDate: ((processesDate || {}).items || []).length - ? processesDate.items[0].scan_time - : '-' + : false }; return syscollector;