diff --git a/CHANGELOG.md b/CHANGELOG.md index f35ec8ff36..01659167b5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,7 @@ All notable changes to the Wazuh app project will be documented in this file. - Changed empty fields in FIM tables and `syscheck.value_name` in discovery now show an empty tag for visual clarity [#3279](https://github.com/wazuh/wazuh-kibana-app/pull/3279) - Adapted the Mitre tactics and techniques resources to use the API endpoints [#3346](https://github.com/wazuh/wazuh-kibana-app/pull/3346) - Refactored all try catch strategy on Settings section [#3392](https://github.com/wazuh/wazuh-kibana-app/pull/3392) +- Refactored all try catch strategy on Controller/Agent section [#3398](https://github.com/wazuh/wazuh-kibana-app/issues/3398) ### Fixed diff --git a/public/controllers/agent/agents-preview.js b/public/controllers/agent/agents-preview.js index 7983a31c50..29fdaecb38 100644 --- a/public/controllers/agent/agents-preview.js +++ b/public/controllers/agent/agents-preview.js @@ -21,8 +21,12 @@ import { ShareAgent } from '../../factories/share-agent'; import { formatUIDate } from '../../react-services/time-service'; import { ErrorHandler } from '../../react-services/error-handler'; import { getDataPlugin, getToasts } from '../../kibana-services'; -import { connect } from 'react-redux'; import store from '../../redux/store'; +import { UI_LOGGER_LEVELS } from '../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../react-services/common-services'; + +const errorContext = 'AgentsPreviewController'; export class AgentsPreviewController { /** @@ -32,15 +36,7 @@ export class AgentsPreviewController { * @param {Object} errorHandler * @param {Object} csvReq */ - constructor( - $scope, - $location, - $route, - errorHandler, - csvReq, - commonData, - $window - ) { + constructor($scope, $location, $route, errorHandler, csvReq, commonData, $window) { this.$scope = $scope; this.genericReq = GenericRequest; this.$location = $location; @@ -62,14 +58,11 @@ export class AgentsPreviewController { this.api = JSON.parse(AppState.getCurrentAPI()).id; const loc = this.$location.search(); if ((loc || {}).agent && (loc || {}).agent !== '000') { - this.commonData.setTimefilter( getDataPlugin().timefilter.timefilter.getTime()); + this.commonData.setTimefilter(getDataPlugin().timefilter.timefilter.getTime()); return this.showAgent({ id: loc.agent }); } - this.isClusterEnabled = - AppState.getClusterInfo() && - AppState.getClusterInfo().status === 'enabled'; - + this.isClusterEnabled = AppState.getClusterInfo() && AppState.getClusterInfo().status === 'enabled'; this.loading = true; this.osPlatforms = []; this.versions = []; @@ -77,7 +70,7 @@ export class AgentsPreviewController { this.nodes = []; this.mostActiveAgent = { name: '', - id: '' + id: '', }; this.prevSearch = false; @@ -95,16 +88,14 @@ export class AgentsPreviewController { } else { this.hasAgents = true; } - // Watcher for URL params this.$scope.$watch('submenuNavItem', () => { this.$location.search('tab', this.submenuNavItem); }); - this.$scope.$on('wazuhFetched', evt => { + this.$scope.$on('wazuhFetched', (evt) => { evt.stopPropagation(); }); - this.registerAgentsProps = { addNewAgent: flag => this.addNewAgent(flag), hasAgents: this.hasAgents, @@ -126,7 +117,7 @@ export class AgentsPreviewController { this.downloadCsv(filters); this.$scope.$applyAsync(); }, - showAgent: agent => { + showAgent: (agent) => { this.showAgent(agent); this.$scope.$applyAsync(); }, @@ -134,18 +125,11 @@ export class AgentsPreviewController { return await this.getMostActive(); }, clickAction: (item, openAction = false) => { - clickAction( - item, - openAction, - instance, - this.shareAgent, - this.$location, - this.$scope - ); + clickAction(item, openAction, instance, this.shareAgent, this.$location, this.$scope); this.$scope.$applyAsync(); }, - formatUIDate: date => formatUIDate(date), - summary: this.summary + formatUIDate: (date) => formatUIDate(date), + summary: this.summary, }; //Load this.load(); @@ -175,10 +159,7 @@ export class AgentsPreviewController { */ async downloadCsv(filters) { try { - ErrorHandler.info( - 'Your download should begin automatically...', - 'CSV' - ); + ErrorHandler.info('Your download should begin automatically...', 'CSV'); const output = await this.csvReq.fetch('/agents', this.api, filters); const blob = new Blob([output], { type: 'text/csv' }); // eslint-disable-line @@ -186,7 +167,17 @@ export class AgentsPreviewController { return; } catch (error) { - ErrorHandler.handle(error, 'Download CSV'); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + error: { + error: error, + message: error.message || error, + title: `Error exporting CSV: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } return; } @@ -195,12 +186,16 @@ export class AgentsPreviewController { try { const data = await this.genericReq.request( 'GET', - `/elastic/top/${this.firstUrlParam}/${this.secondUrlParam}/agent.name/${this.pattern}?agentsList=${store.getState().appStateReducers.allowedAgents.toString()}` + `/elastic/top/${this.firstUrlParam}/${this.secondUrlParam}/agent.name/${ + this.pattern + }?agentsList=${store.getState().appStateReducers.allowedAgents.toString()}` ); this.mostActiveAgent.name = data.data.data; const info = await this.genericReq.request( 'GET', - `/elastic/top/${this.firstUrlParam}/${this.secondUrlParam}/agent.id/${this.pattern}?agentsList=${store.getState().appStateReducers.allowedAgents.toString()}` + `/elastic/top/${this.firstUrlParam}/${this.secondUrlParam}/agent.id/${ + this.pattern + }?agentsList=${store.getState().appStateReducers.allowedAgents.toString()}` ); if (info.data.data === '' && this.mostActiveAgent.name !== '') { this.mostActiveAgent.id = '000'; @@ -208,8 +203,21 @@ export class AgentsPreviewController { this.mostActiveAgent.id = info.data.data; } return this.mostActiveAgent; - } catch (error) { - getToasts().addDanger({title: 'An error occurred while trying to get the most active agent', text: error.message || error }); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `An error occurred while trying to get the most active agent: ${ + error.message || error + }`, + }, + }; + getErrorOrchestrator().handleError(options); } } @@ -219,14 +227,23 @@ export class AgentsPreviewController { async load() { try { this.errorInit = false; - const clusterInfo = AppState.getClusterInfo(); - this.firstUrlParam = - clusterInfo.status === 'enabled' ? 'cluster' : 'manager'; + this.firstUrlParam = clusterInfo.status === 'enabled' ? 'cluster' : 'manager'; this.secondUrlParam = clusterInfo[this.firstUrlParam]; this.pattern = (await getDataPlugin().indexPatterns.get(AppState.getCurrentPattern())).title; } catch (error) { - this.errorInit = ErrorHandler.handle(error, '', { silent: true }); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.CRITICAL, + store: true, + error: { + error: error, + message: error.message || error, + title: error.message || error, + }, + }; + getErrorOrchestrator().handleError(options); } this.loading = false; this.$scope.$applyAsync(); @@ -250,14 +267,24 @@ export class AgentsPreviewController { try { const result = await this.genericReq.request('GET', '/hosts/apis'); const entries = result.data || []; - const host = entries.filter(e => { + const host = entries.filter((e) => { return e.id == this.api; }); const url = host[0].url; const numToClean = url.startsWith('https://') ? 8 : 7; return url.substr(numToClean); } catch (error) { - return false; + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.UI, + error: { + error: error, + message: error.message || error, + title: `Could not get the Wazuh API address: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } } @@ -268,8 +295,19 @@ export class AgentsPreviewController { try { const data = await WzRequest.apiReq('GET', '//', {}); const result = ((data || {}).data || {}).data || {}; - return result.api_version + return result.api_version; } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + error: { + error: error, + message: error.message || error, + title: `Could not get the Wazuh version: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); return version; } } diff --git a/public/controllers/agent/agents.js b/public/controllers/agent/agents.js index 18de8d6b00..c44e32e3df 100644 --- a/public/controllers/agent/agents.js +++ b/public/controllers/agent/agents.js @@ -20,7 +20,7 @@ import { AppState } from '../../react-services/app-state'; import { WazuhConfig } from '../../react-services/wazuh-config'; import { GenericRequest } from '../../react-services/generic-request'; import { WzRequest } from '../../react-services/wz-request'; -import { getToasts } from '../../kibana-services'; +import { getToasts } from '../../kibana-services'; import { ShareAgent } from '../../factories/share-agent'; import { TabVisualizations } from '../../factories/tab-visualizations'; import { formatUIDate } from '../../react-services/time-service'; @@ -31,6 +31,11 @@ import { updateGlobalBreadcrumb } from '../../redux/actions/globalBreadcrumbActi import { WAZUH_ALERTS_PATTERN } from '../../../common/constants'; import { getDataPlugin } from '../../kibana-services'; import { hasAgentSupportModule } from '../../react-services/wz-agents'; +import { UI_LOGGER_LEVELS } from '../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../react-services/common-services'; + +const errorContext = 'AgentsController'; export class AgentsController { /** * Class constructor @@ -52,7 +57,6 @@ export class AgentsController { reportingService, visFactoryService, csvReq - ) { this.$scope = $scope; this.$location = $location; @@ -71,9 +75,7 @@ export class AgentsController { // Config on-demand this.$scope.isArray = Array.isArray; - this.configurationHandler = new ConfigurationHandler( - errorHandler - ); + this.configurationHandler = new ConfigurationHandler(errorHandler); this.$scope.currentConfig = null; this.$scope.configurationTab = ''; this.$scope.configurationSubTab = ''; @@ -104,7 +106,7 @@ export class AgentsController { false, false, false, - false + false, ]; } @@ -141,8 +143,7 @@ export class AgentsController { this.$scope.tab = this.commonData.checkTabLocation(); } this.tabHistory = []; - if (!this.ignoredTabs.includes(this.$scope.tab)) - this.tabHistory.push(this.$scope.tab); + if (!this.ignoredTabs.includes(this.$scope.tab)) this.tabHistory.push(this.$scope.tab); // Tab names this.$scope.tabNames = TabNames; @@ -154,28 +155,21 @@ export class AgentsController { * @param {Object} item * @param {Array} array */ - this.$scope.inArray = (item, array) => - item && Array.isArray(array) && array.includes(item); + this.$scope.inArray = (item, array) => item && Array.isArray(array) && array.includes(item); - this.$scope.switchSubtab = async ( - subtab, - force = false, - onlyAgent = false - ) => this.switchSubtab(subtab, force, onlyAgent); + this.$scope.switchSubtab = async (subtab, force = false, onlyAgent = false) => + this.switchSubtab(subtab, force, onlyAgent); this.changeAgent = false; this.$scope.switchTab = (tab, force = false) => this.switchTab(tab, force); - this.$scope.getAgentStatusClass = agentStatus => - agentStatus === 'active' ? 'teal' : 'red'; + this.$scope.getAgentStatusClass = (agentStatus) => (agentStatus === 'active' ? 'teal' : 'red'); - this.$scope.formatAgentStatus = agentStatus => { - return ['active', 'disconnected'].includes(agentStatus) ? - agentStatus : - 'never connected'; + this.$scope.formatAgentStatus = (agentStatus) => { + return ['active', 'disconnected'].includes(agentStatus) ? agentStatus : 'never connected'; }; - this.$scope.getAgent = async newAgentId => this.getAgent(newAgentId); + this.$scope.getAgent = async (newAgentId) => this.getAgent(newAgentId); this.$scope.goGroups = (agent, group) => this.goGroups(agent, group); this.$scope.downloadCsv = async (path, fileName, filters = []) => this.downloadCsv(path, fileName, filters); @@ -183,19 +177,19 @@ export class AgentsController { this.$scope.search = (term, specificPath) => this.$scope.$broadcast('wazuhSearch', { term, - specificPath + specificPath, }); this.$scope.searchSyscheckFile = (term, specificFilter) => this.$scope.$broadcast('wazuhSearch', { term, - specificFilter + specificFilter, }); this.$scope.searchRootcheck = (term, specificFilter) => this.$scope.$broadcast('wazuhSearch', { term, - specificFilter + specificFilter, }); this.$scope.launchRootcheckScan = () => this.launchRootcheckScan(); @@ -203,8 +197,7 @@ export class AgentsController { this.$scope.startVis2Png = () => this.startVis2Png(); - this.$scope.shouldShowComponent = component => - this.shouldShowComponent(component); + this.$scope.shouldShowComponent = (component) => this.shouldShowComponent(component); this.$scope.$on('$destroy', () => { this.visFactoryService.clearAll(); @@ -217,27 +210,16 @@ export class AgentsController { this.$location.path('/manager/groups'); }; - this.$scope.exportConfiguration = enabledComponents => { - this.reportingService.startConfigReport( - this.$scope.agent, - 'agentConfig', - enabledComponents - ); + this.$scope.exportConfiguration = (enabledComponents) => { + this.reportingService.startConfigReport(this.$scope.agent, 'agentConfig', enabledComponents); }; - this.$scope.restartAgent = async agent => { + this.$scope.restartAgent = async (agent) => { this.$scope.restartingAgent = true; try { - const data = await WzRequest.apiReq( - 'PUT', - `/agents/${agent.id}/restart`, - {} - ); + const data = await WzRequest.apiReq('PUT', `/agents/${agent.id}/restart`, {}); const result = ((data || {}).data || {}).data || false; - const failed = - result && - Array.isArray(result.failed_items) && - result.failed_items.length; + const failed = result && Array.isArray(result.failed_items) && result.failed_items.length; if (failed) { throw new Error(result.failed_items[0].detail); } else if (result) { @@ -247,7 +229,18 @@ export class AgentsController { } this.$scope.restartingAgent = false; } catch (error) { - ErrorHandler.handle(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Error restarting the agent: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); this.$scope.restartingAgent = false; } this.$scope.$applyAsync(); @@ -256,41 +249,51 @@ export class AgentsController { //Load try { this.$scope.getAgent(); - } catch (e) { - ErrorHandler.handle( - 'Unexpected exception loading controller', - 'Agents' - ); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Error getting the agent: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } // Config on demand this.$scope.getXML = () => this.configurationHandler.getXML(this.$scope); this.$scope.getJSON = () => this.configurationHandler.getJSON(this.$scope); - this.$scope.isString = item => typeof item === 'string'; - this.$scope.hasSize = obj => - obj && typeof obj === 'object' && Object.keys(obj).length; - this.$scope.offsetTimestamp = (text, time) => - this.offsetTimestamp(text, time); - this.$scope.switchConfigTab = ( - configurationTab, - sections, - navigate = true - ) => { + this.$scope.isString = (item) => typeof item === 'string'; + this.$scope.hasSize = (obj) => obj && typeof obj === 'object' && Object.keys(obj).length; + this.$scope.offsetTimestamp = (text, time) => this.offsetTimestamp(text, time); + this.$scope.switchConfigTab = (configurationTab, sections, navigate = true) => { this.$scope.navigate = navigate; try { this.$scope.configSubTab = JSON.stringify({ configurationTab: configurationTab, - sections: sections + sections: sections, }); if (!this.$location.search().configSubTab) { - AppState.setSessionStorageItem( - 'configSubTab', - this.$scope.configSubTab - ); + AppState.setSessionStorageItem('configSubTab', this.$scope.configSubTab); this.$location.search('configSubTab', true); } } catch (error) { - ErrorHandler.handle(error, 'Set configuration path'); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `${error.message || error} Set configuration path`, + }, + }; + getErrorOrchestrator().handleError(options); } this.configurationHandler.switchConfigTab( configurationTab, @@ -306,21 +309,14 @@ export class AgentsController { if (!this.$location.search().configWodle) { this.$location.search('configWodle', this.$scope.configWodle); } - this.configurationHandler.switchWodle( - wodleName, - this.$scope, - this.$scope.agent.id - ); + this.configurationHandler.switchWodle(wodleName, this.$scope, this.$scope.agent.id); }; this.$scope.switchConfigurationTab = (configurationTab, navigate) => { // Check if configuration is synced this.checkSync(); this.$scope.navigate = navigate; - this.configurationHandler.switchConfigurationTab( - configurationTab, - this.$scope - ); + this.configurationHandler.switchConfigurationTab(configurationTab, this.$scope); if (!this.$scope.navigate) { const configSubTab = this.$location.search().configSubTab; if (configSubTab) { @@ -333,7 +329,7 @@ export class AgentsController { false ); } catch (error) { - ErrorHandler.handle(error, 'Get configuration path'); + throw new Error(error); } } else { const configWodle = this.$location.search().configWodle; @@ -347,11 +343,8 @@ export class AgentsController { this.$location.search('configWodle', null); } }; - this.$scope.switchConfigurationSubTab = configurationSubTab => { - this.configurationHandler.switchConfigurationSubTab( - configurationSubTab, - this.$scope - ); + this.$scope.switchConfigurationSubTab = (configurationSubTab) => { + this.configurationHandler.switchConfigurationSubTab(configurationSubTab, this.$scope); if (configurationSubTab === 'pm-sca') { this.$scope.currentConfig.sca = this.configurationHandler.parseWodle( this.$scope.currentConfig, @@ -359,8 +352,8 @@ export class AgentsController { ); } }; - this.$scope.updateSelectedItem = i => (this.$scope.selectedItem = i); - this.$scope.getIntegration = list => + this.$scope.updateSelectedItem = (i) => (this.$scope.selectedItem = i); + this.$scope.getIntegration = (list) => this.configurationHandler.getIntegration(list, this.$scope); this.$scope.switchScaScan = () => { @@ -368,7 +361,7 @@ export class AgentsController { if (!this.$scope.showScaScan) { this.$scope.$emit('changeTabView', { tabView: this.$scope.tabView, - tab: this.$scope.tab + tab: this.$scope.tab, }); } this.$scope.$applyAsync(); @@ -387,51 +380,55 @@ export class AgentsController { this.switchGroupEdit(); }; - this.$scope.showConfirmAddGroup = group => { - this.$scope.addingGroupToAgent = this.$scope.addingGroupToAgent - ? false - : group; + this.$scope.showConfirmAddGroup = (group) => { + this.$scope.addingGroupToAgent = this.$scope.addingGroupToAgent ? false : group; }; this.$scope.cancelAddGroup = () => (this.$scope.addingGroupToAgent = false); - this.$scope.loadScaChecks = policy => + this.$scope.loadScaChecks = (policy) => (this.$scope.lookingSca = { ...policy, - id: policy.policy_id + id: policy.policy_id, }); this.$scope.closeScaChecks = () => (this.$scope.lookingSca = false); - this.$scope.confirmAddGroup = group => { - this.groupHandler - .addAgentToGroup(group, this.$scope.agent.id) - .then(() => WzRequest.apiReq('GET', `/agents`, { + this.$scope.confirmAddGroup = async (group) => { + try { + await this.groupHandler.addAgentToGroup(group, this.$scope.agent.id); + const response = await WzRequest.apiReq('GET', `/agents`, { params: { agents_list: this.$scope.agent.id, - } - })) - .then(agent => { - this.$scope.agent.group = agent.data.data.affected_items[0].group; - this.$scope.groups = this.$scope.groups.filter( - item => !agent.data.data.affected_items[0].group.includes(item) - ); - this.$scope.addingGroupToAgent = false; - this.$scope.editGroup = false; - ErrorHandler.info(`Group ${group} has been added.`); - this.$scope.$applyAsync(); - }) - .catch(error => { - this.$scope.editGroup = false; - this.$scope.addingGroupToAgent = false; - ErrorHandler.handle( - error.message || error, - 'Error adding group to agent' - ); + }, }); + this.$scope.agent.group = response.data.data.affected_items[0].group; + this.$scope.groups = this.$scope.groups.filter( + (item) => !responseP.data.data.affected_items[0].group.includes(item) + ); + this.$scope.addingGroupToAgent = false; + this.$scope.editGroup = false; + ErrorHandler.info(`Group ${group} has been added.`); + this.$scope.$applyAsync(); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Error adding group: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); + this.$scope.editGroup = false; + this.$scope.addingGroupToAgent = false; + } }; - this.$scope.expand = i => this.expand(i); + this.$scope.expand = (i) => this.expand(i); this.setTabs(); } @@ -461,14 +458,13 @@ export class AgentsController { } else { this.$scope.$emit('changeTabView', { tabView: subtab, - tab: this.$scope.tab + tab: this.$scope.tab, }); } this.$scope.tabView = subtab; return; } catch (error) { - ErrorHandler.handle(error, 'Agents'); - return; + throw new Error(error); } } @@ -487,46 +483,46 @@ export class AgentsController { this.commonData.setRefreshInterval(timefilter.getRefreshInterval()); timefilter.setRefreshInterval({ pause: true, - value: 0 + value: 0, }); } else if (this.ignoredTabs.includes(this.$scope.tab)) { timefilter.setRefreshInterval(this.commonData.getRefreshInterval()); } - if(tab === 'syscollector'){ // TODO: Migrate syscollector to React + if (tab === 'syscollector') { + // TODO: Migrate syscollector to React let breadcrumb = [ - { - text: '', - }, - { - text: 'Agents', - href: "#/agents-preview" - }, - { agent: this.$scope.agent }, - { - text: 'Inventory Data', - className: 'wz-global-breadcrumb-popover' - }, - ]; + { + text: '', + }, + { + text: 'Agents', + href: '#/agents-preview', + }, + { agent: this.$scope.agent }, + { + text: 'Inventory Data', + className: 'wz-global-breadcrumb-popover', + }, + ]; store.dispatch(updateGlobalBreadcrumb(breadcrumb)); - $('#breadcrumbNoTitle').attr("title",""); + $('#breadcrumbNoTitle').attr('title', ''); } // Update agent status if (!force && ((this.$scope || {}).agent || false)) { try { - const agentInfo = await WzRequest.apiReq( - 'GET', - `/agents`, { - params: { - agents_list: this.$scope.agent.id, - select: 'status' - } - } - ); + const agentInfo = await WzRequest.apiReq('GET', `/agents`, { + params: { + agents_list: this.$scope.agent.id, + select: 'status', + }, + }); this.$scope.agent.status = (((((agentInfo || {}).data || {}).data || {}).affected_items || [])[0] || {}).status || this.$scope.agent.status; - } catch (error) { } // eslint-disable-line + } catch (error) { + throw new Error(error); + } } try { @@ -535,15 +531,17 @@ export class AgentsController { //remove to component this.$scope.scaProps = { agent: this.$scope.agent, - loadScaChecks: policy => this.$scope.loadScaChecks(policy), - downloadCsv: (path, name) => this.downloadCsv(path, name) + loadScaChecks: (policy) => this.$scope.loadScaChecks(policy), + downloadCsv: (path, name) => this.downloadCsv(path, name), }; } if (tab === 'syscollector') try { await this.loadSyscollector(this.$scope.agent.id); - } catch (error) { } // eslint-disable-line + } catch (error) { + throw new Error(error); + } if (tab === 'configuration') { this.$scope.switchConfigurationTab('welcome'); } else { @@ -551,8 +549,7 @@ export class AgentsController { } if (!this.ignoredTabs.includes(tab)) this.tabHistory.push(tab); - if (this.tabHistory.length > 2) - this.tabHistory = this.tabHistory.slice(-2); + if (this.tabHistory.length > 2) this.tabHistory = this.tabHistory.slice(-2); if (this.$scope.tab === tab && !force) { this.$scope.$applyAsync(); @@ -563,37 +560,40 @@ export class AgentsController { const sameTab = this.$scope.tab === tab; this.$location.search('tab', tab); const preserveDiscover = - this.tabHistory.length === 2 && - this.tabHistory[0] === this.tabHistory[1] && - !force; + this.tabHistory.length === 2 && this.tabHistory[0] === this.tabHistory[1] && !force; this.$scope.tab = tab; const targetSubTab = - this.targetLocation && typeof this.targetLocation === 'object' ? - this.targetLocation.subTab : - 'panels'; + this.targetLocation && typeof this.targetLocation === 'object' + ? this.targetLocation.subTab + : 'panels'; if (!this.ignoredTabs.includes(this.$scope.tab)) { - this.$scope.switchSubtab( - targetSubTab, - true, - onlyAgent, - sameTab, - preserveDiscover - ); + this.$scope.switchSubtab(targetSubTab, true, onlyAgent, sameTab, preserveDiscover); } this.shareAgent.deleteTargetLocation(); this.targetLocation = null; this.$scope.$applyAsync(); } catch (error) { - return Promise.reject(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.CRITICAL, + store: true, + error: { + error: error, + message: error.message || error, + title: error.message || error, + }, + }; + getErrorOrchestrator().handleError(options); } this.$scope.configurationTabsProps = {}; - this.$scope.buildProps = tabs => { + this.$scope.buildProps = (tabs) => { const cleanTabs = []; - tabs.forEach(x => { + tabs.forEach((x) => { if ( this.$scope.configurationTab === 'integrity-monitoring' && x.id === 'fim-whodata' && @@ -604,18 +604,15 @@ export class AgentsController { cleanTabs.push({ id: x.id, - name: x.name + name: x.name, }); }); this.$scope.configurationTabsProps = { - clickAction: tab => { + clickAction: (tab) => { this.$scope.switchConfigurationSubTab(tab); }, - selectedTab: - this.$scope.configurationSubTab || (tabs && tabs.length) - ? tabs[0].id - : '', - tabs: cleanTabs + selectedTab: this.$scope.configurationSubTab || (tabs && tabs.length) ? tabs[0].id : '', + tabs: cleanTabs, }; }; @@ -627,9 +624,11 @@ export class AgentsController { * @param {*} id */ addMitrefilter(id) { - const filter = `{"meta":{"index": ${AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN}},"query":{"match":{"rule.mitre.id":{"query":"${id}","type":"phrase"}}}}`; + const filter = `{"meta":{"index": ${ + AppState.getCurrentPattern() || WAZUH_ALERTS_PATTERN + }},"query":{"match":{"rule.mitre.id":{"query":"${id}","type":"phrase"}}}}`; this.$rootScope.$emit('addNewKibanaFilter', { - filter: JSON.parse(filter) + filter: JSON.parse(filter), }); } @@ -639,10 +638,7 @@ export class AgentsController { setTabs() { this.$scope.agentsTabsProps = false; if (this.$scope.agent) { - this.currentPanel = this.commonData.getCurrentPanel( - this.$scope.tab, - true - ); + this.currentPanel = this.commonData.getCurrentPanel(this.$scope.tab, true); if (!this.currentPanel) return; @@ -653,27 +649,23 @@ export class AgentsController { ); const cleanTabs = []; - tabs.forEach(x => { - if (!hasAgentSupportModule(this.$scope.agent, x.id) - ) - return; + tabs.forEach((x) => { + if (!hasAgentSupportModule(this.$scope.agent, x.id)) return; cleanTabs.push({ id: x.id, - name: x.name + name: x.name, }); }); this.$scope.agentsTabsProps = { - clickAction: tab => { + clickAction: (tab) => { this.switchTab(tab, true); }, selectedTab: this.$scope.tab || - (this.currentPanel && this.currentPanel.length - ? this.currentPanel[0] - : ''), - tabs: cleanTabs + (this.currentPanel && this.currentPanel.length ? this.currentPanel[0] : ''), + tabs: cleanTabs, }; this.$scope.$applyAsync(); } @@ -684,43 +676,55 @@ export class AgentsController { color: color, title: title, text: text, - toastLifeTimeMs: time + toastLifeTimeMs: time, }); }; goDiscover() { this.targetLocation = { tab: 'general', - subTab: 'discover' + subTab: 'discover', }; return this.switchTab('general'); } - onClickUpgrade() { + async onClickUpgrade() { try { - WzRequest.apiReq('PUT', `/agents/${this.$scope.agent.id}/upgrade`, {}) - .then(() => { - this.showToast('success', 'The agent is being upgrade.', '', 5000); - }) - .catch(() => { - this.showToast('warning', 'This agent is already upgrade.', '', 5000); - }); + await WzRequest.apiReq('PUT', `/agents/${this.$scope.agent.id}/upgrade`, {}); + this.showToast('success', 'The agent is being upgrade.', '', 5000); } catch (error) { - console.log(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Error upgrading the agent: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } } - onClickRestart() { + async onClickRestart() { try { - WzRequest.apiReq('PUT', `/agents/${this.$scope.agent.id}/restart`, {}) - .then(() => { - this.showToast('success', 'Agent restarted.', '', 5000); - }) - .catch(() => { - this.showToast('warning', 'Error restarting agent.', '', 5000); - }); + await WzRequest.apiReq('PUT', `/agents/${this.$scope.agent.id}/restart`, {}); + this.showToast('success', 'Agent restarted.', '', 5000); } catch (error) { - console.log(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Error restarting the agent: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } } @@ -756,7 +760,8 @@ export class AgentsController { async checkSync() { const isSync = await WzRequest.apiReq( 'GET', - `/agents/${this.$scope.agent.id}/group/is_sync`, {} + `/agents/${this.$scope.agent.id}/group/is_sync`, + {} ); this.$scope.isSynchronized = (((((isSync || {}).data || {}).data || {}).affected_items || [])[0] || {}).synced || false; @@ -769,15 +774,11 @@ export class AgentsController { */ async loadSyscollector(id) { try { - const syscollectorData = await this.genericReq.request( - 'GET', - `/api/syscollector/${id}` - ); + const syscollectorData = await this.genericReq.request('GET', `/api/syscollector/${id}`); this.$scope.syscollector = (syscollectorData || {}).data || {}; - return; } catch (error) { - return Promise.reject(error); + throw new Error(error); } } @@ -799,7 +800,7 @@ export class AgentsController { const data = await WzRequest.apiReq('GET', `/agents`, { params: { agents_list: id, - } + }, }); const agentInfo = ((((data || {}).data || {}).data || {}).affected_items || [])[0] || false; @@ -808,12 +809,9 @@ export class AgentsController { if (!this.$scope.agent) return; if (agentInfo && this.$scope.agent.os) { - this.$scope.agentOS = - this.$scope.agent.os.name + ' ' + this.$scope.agent.os.version; + this.$scope.agentOS = this.$scope.agent.os.name + ' ' + this.$scope.agent.os.version; const isLinux = this.$scope.agent.os.uname.includes('Linux'); - this.$scope.agent.agentPlatform = isLinux - ? 'linux' - : this.$scope.agent.os.platform; + this.$scope.agent.agentPlatform = isLinux ? 'linux' : this.$scope.agent.os.platform; } else { this.$scope.agentOS = '-'; this.$scope.agent.agentPlatform = false; @@ -822,16 +820,13 @@ export class AgentsController { await this.$scope.switchTab(this.$scope.tab, true); const groups = await WzRequest.apiReq('GET', '/groups', {}); this.$scope.groups = groups.data.data.affected_items - .map(item => item.name) - .filter( - item => - this.$scope.agent.group && !this.$scope.agent.group.includes(item) - ); + .map((item) => item.name) + .filter((item) => this.$scope.agent.group && !this.$scope.agent.group.includes(item)); this.loadWelcomeCardsProps(); this.$scope.getWelcomeCardsProps = (resultState) => { - return {...this.$scope.welcomeCardsProps, resultState } - } + return { ...this.$scope.welcomeCardsProps, resultState }; + }; this.$scope.load = false; this.$scope.$applyAsync(); return; @@ -841,31 +836,24 @@ export class AgentsController { this.$scope.emptyAgent = 'Wazuh API timeout.'; } } - if ( - error && - typeof error === 'string' && - error.includes('Agent does not exist') - ) { + if (error && typeof error === 'string' && error.includes('Agent does not exist')) { this.$location.search('agent', null); this.$location.path('/agents-preview'); } + this.$scope.load = false; + this.$scope.$applyAsync(); + throw new Error(error); } - - this.$scope.load = false; - this.$scope.$applyAsync(); - return; } shouldShowComponent(component) { - return hasAgentSupportModule(this.$scope.agent, component) + return hasAgentSupportModule(this.$scope.agent, component); } cleanExtensions(extensions) { const result = {}; for (const extension in extensions) { - if ( - hasAgentSupportModule(this.$scope.agent, extension) - ) { + if (hasAgentSupportModule(this.$scope.agent, extension)) { result[extension] = extensions[extension]; } } @@ -877,7 +865,7 @@ export class AgentsController { */ loadWelcomeCardsProps() { this.$scope.welcomeCardsProps = { - switchTab: tab => this.switchTab(tab), + switchTab: (tab) => this.switchTab(tab), extensions: this.cleanExtensions(this.$scope.extensions), agent: this.$scope.agent, api: AppState.getCurrentAPI(), @@ -885,7 +873,7 @@ export class AgentsController { setExtensions: (api, extensions) => { AppState.setExtensions(api, extensions); this.$scope.extensions = extensions; - } + }, }; } @@ -903,6 +891,18 @@ export class AgentsController { try { return text + formatUIDate(time); } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: false, + error: { + error: error, + message: error.message || error, + title: error.message || error, + }, + }; + getErrorOrchestrator().handleError(options); return time !== '-' ? `${text}${time} (UTC)` : time; } } @@ -914,7 +914,7 @@ export class AgentsController { */ goGroups(agent, group) { AppState.setNavigation({ - status: true + status: true, }); this.visFactoryService.clearAll(); this.shareAgent.setAgent(agent, group); @@ -931,19 +931,15 @@ export class AgentsController { */ async downloadCsv(path, fileName, filters = []) { try { - ErrorHandler.info( - 'Your download should begin automatically...', - 'CSV' - ); + ErrorHandler.info('Your download should begin automatically...', 'CSV'); const currentApi = JSON.parse(AppState.getCurrentAPI()).id; const output = await this.csvReq.fetch(path, currentApi, filters); const blob = new Blob([output], { - type: 'text/csv' + type: 'text/csv', }); // eslint-disable-line - FileSaver.saveAs(blob, fileName); } catch (error) { - ErrorHandler.handle(error, 'Download CSV'); + throw new Error(error); } return; } @@ -957,9 +953,7 @@ export class AgentsController { syscollectorFilters.push( this.filterHandler.managerQuery(AppState.getClusterInfo().cluster, true) ); - syscollectorFilters.push( - this.filterHandler.agentQuery(this.$scope.agent.id) - ); + syscollectorFilters.push(this.filterHandler.agentQuery(this.$scope.agent.id)); } this.reportingService.startVis2Png( this.$scope.tab, @@ -974,15 +968,23 @@ export class AgentsController { if (!isActive) { throw new Error('Agent is not active'); } - await WzRequest.apiReq( - 'PUT', - `/rootcheck/${this.$scope.agent.id}`, - {} - ); + await WzRequest.apiReq('PUT', `/rootcheck/${this.$scope.agent.id}`, {}); ErrorHandler.info( - `Policy monitoring scan launched successfully on agent ${this.$scope.agent.id}`); + `Policy monitoring scan launched successfully on agent ${this.$scope.agent.id}` + ); } catch (error) { - ErrorHandler.handle(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: ` Policy monitoring scan failed on agent ${this.$scope.agent.id} due to: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } return; } @@ -995,15 +997,23 @@ export class AgentsController { } await WzRequest.apiReq('PUT', `/syscheck`, { params: { - agents_list: this.$scope.agent.id - } + agents_list: this.$scope.agent.id, + }, }); - ErrorHandler.info( - `FIM scan launched successfully on agent ${this.$scope.agent.id}`, - '' - ); + ErrorHandler.info(`FIM scan launched successfully on agent ${this.$scope.agent.id}`, ''); } catch (error) { - ErrorHandler.handle(error); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: ` FIM scan failed on agent ${this.$scope.agent.id} due to: ${error.message || error}`, + }, + }; + getErrorOrchestrator().handleError(options); } return; } @@ -1025,7 +1035,7 @@ export class AgentsController { false, false, false, - false + false, ]; } diff --git a/public/controllers/agent/components/agents-preview.js b/public/controllers/agent/components/agents-preview.js index a64590abbd..9257ac2764 100644 --- a/public/controllers/agent/components/agents-preview.js +++ b/public/controllers/agent/components/agents-preview.js @@ -22,11 +22,10 @@ import { EuiLoadingChart, EuiSpacer, EuiEmptyPrompt, - EuiToolTip + EuiToolTip, } from '@elastic/eui'; -import { Pie } from "../../../components/d3/pie"; -import { ProgressChart } from "../../../components/d3/progress"; -import { AgentsTable } from './agents-table' +import { Pie } from '../../../components/d3/pie'; +import { AgentsTable } from './agents-table'; import { WzRequest } from '../../../react-services/wz-request'; import KibanaVis from '../../../kibana-integrations/kibana-vis'; import WzReduxProvider from '../../../redux/wz-redux-provider'; @@ -36,11 +35,20 @@ import { FilterHandler } from '../../../utils/filter-handler'; import { TabVisualizations } from '../../../factories/tab-visualizations'; import { WazuhConfig } from './../../../react-services/wazuh-config.js'; import { WzDatePicker } from '../../../components/wz-date-picker/wz-date-picker'; -import { withReduxProvider, withGlobalBreadcrumb, withUserAuthorizationPrompt } from '../../../components/common/hocs'; +import { + withReduxProvider, + withGlobalBreadcrumb, + withUserAuthorizationPrompt, +} from '../../../components/common/hocs'; import { formatUIDate } from '../../../../public/react-services/time-service'; import { compose } from 'redux'; -import { withErrorBoundary } from '../../../components/common/hocs' -import './agents-preview.scss' +import { withErrorBoundary } from '../../../components/common/hocs'; +import './agents-preview.scss'; +import { UI_LOGGER_LEVELS } from '../../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../../react-services/common-services'; + +const errorContext = 'AgentsPreview'; const FILTER_ACTIVE = 'active'; const FILTER_DISCONNECTED = 'disconnected'; @@ -50,282 +58,340 @@ export const AgentsPreview = compose( withErrorBoundary, withReduxProvider, withGlobalBreadcrumb([{ text: '' }, { text: 'Agents' }]), - withUserAuthorizationPrompt([[{action: 'agent:read', resource: 'agent:id:*'},{action: 'agent:read', resource: 'agent:group:*'}]]) -)(class AgentsPreview extends Component { - _isMount = false; - constructor(props) { - super(props); - this.state = { data: [], loading: false, showAgentsEvolutionVisualization: false, agentTableFilters: [] }; - this.wazuhConfig = new WazuhConfig(); - this.agentStatusLabelToIDMap = { - 'Active': 'active', - 'Disconnected': 'disconnected', - 'Never connected': 'never_connected' + withUserAuthorizationPrompt([ + [ + { action: 'agent:read', resource: 'agent:id:*' }, + { action: 'agent:read', resource: 'agent:group:*' }, + ], + ]) +)( + class AgentsPreview extends Component { + _isMount = false; + constructor(props) { + super(props); + this.state = { + data: [], + loading: false, + showAgentsEvolutionVisualization: false, + agentTableFilters: [], + }; + this.wazuhConfig = new WazuhConfig(); + this.agentStatusLabelToIDMap = { + Active: 'active', + Disconnected: 'disconnected', + 'Never connected': 'never_connected', + }; } - } - async componentDidMount() { - this._isMount = true; - this.getSummary(); - if( this.wazuhConfig.getConfig()['wazuh.monitoring.enabled'] ){ - this._isMount && this.setState({ showAgentsEvolutionVisualization: true }); - const tabVisualizations = new TabVisualizations(); - tabVisualizations.removeAll(); - tabVisualizations.setTab('general'); - tabVisualizations.assign({ - general: 1 - }); - const filterHandler = new FilterHandler(AppState.getCurrentPattern()); - await VisFactoryHandler.buildOverviewVisualizations( - filterHandler, - 'general', - null - ); + async componentDidMount() { + this._isMount = true; + this.getSummary(); + if (this.wazuhConfig.getConfig()['wazuh.monitoring.enabled']) { + this._isMount && this.setState({ showAgentsEvolutionVisualization: true }); + const tabVisualizations = new TabVisualizations(); + tabVisualizations.removeAll(); + tabVisualizations.setTab('general'); + tabVisualizations.assign({ + general: 1, + }); + const filterHandler = new FilterHandler(AppState.getCurrentPattern()); + await VisFactoryHandler.buildOverviewVisualizations(filterHandler, 'general', null); + } } - } - componentWillUnmount() { - this._isMount = false; - } + componentWillUnmount() { + this._isMount = false; + } - agentStatusLabelToID(label){ - return this.agentStatusLabelToIDMap[label]; - } + agentStatusLabelToID(label) { + return this.agentStatusLabelToIDMap[label]; + } - groupBy = function(arr) { - return arr.reduce(function(prev, item) { - if (item in prev) prev[item]++; - else prev[item] = 1; - return prev; - }, {}); - }; + groupBy = function (arr) { + return arr.reduce(function (prev, item) { + if (item in prev) prev[item]++; + else prev[item] = 1; + return prev; + }, {}); + }; - async getSummary() { - try { - this.setState({ loading: true }); - const summaryData = await WzRequest.apiReq('GET', '/agents/summary/status', {}); - this.summary = summaryData.data.data; - this.totalAgents = this.summary.total; - const model = [ - { id: 'active', label: "Active", value: this.summary['active'] || 0 }, - { id: 'disconnected', label: "Disconnected", value: this.summary['disconnected'] || 0 }, - { id: 'neverConnected', label: "Never connected", value: this.summary['never_connected'] || 0 } - ]; - this.setState({ data: model }); - this.agentsCoverity = this.totalAgents ? ((this.summary['active'] || 0) / this.totalAgents) * 100 : 0; - const lastAgent = await WzRequest.apiReq('GET', '/agents', {params: { limit: 1, sort: '-dateAdd', q: 'id!=000' }}); - this.lastAgent = lastAgent.data.data.affected_items[0]; - this.mostActiveAgent = await this.props.tableProps.getMostActive(); - const osresult = await WzRequest.apiReq('GET', '/agents/summary/os', {}); - this.platforms = this.groupBy(osresult.data.data.affected_items); - const platformsModel = []; - for (let [key, value] of Object.entries(this.platforms)) { - platformsModel.push({ id: key, label: key, value: value }); + async getSummary() { + try { + this.setState({ loading: true }); + const summaryData = await WzRequest.apiReq('GET', '/agents/summary/status', {}); + this.summary = summaryData.data.data; + this.totalAgents = this.summary.total; + const model = [ + { id: 'active', label: 'Active', value: this.summary['active'] || 0 }, + { id: 'disconnected', label: 'Disconnected', value: this.summary['disconnected'] || 0 }, + { + id: 'neverConnected', + label: 'Never connected', + value: this.summary['never_connected'] || 0, + }, + ]; + this.setState({ data: model }); + this.agentsCoverity = this.totalAgents + ? ((this.summary['active'] || 0) / this.totalAgents) * 100 + : 0; + const lastAgent = await WzRequest.apiReq('GET', '/agents', { + params: { limit: 1, sort: '-dateAdd', q: 'id!=000' }, + }); + this.lastAgent = lastAgent.data.data.affected_items[0]; + this.mostActiveAgent = await this.props.tableProps.getMostActive(); + const osresult = await WzRequest.apiReq('GET', '/agents/summary/os', {}); + this.platforms = this.groupBy(osresult.data.data.affected_items); + const platformsModel = []; + for (let [key, value] of Object.entries(this.platforms)) { + platformsModel.push({ id: key, label: key, value: value }); + } + this._isMount && this.setState({ platforms: platformsModel, loading: false }); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Could not get the agents summary`, + }, + }; + getErrorOrchestrator().handleError(options); } - this._isMount && - this.setState({ platforms: platformsModel, loading: false }); - } catch (error) {} - } + } - removeFilters(){ - this._isMount && this.setState({agentTableFilters: []}) - } + removeFilters() { + this._isMount && this.setState({ agentTableFilters: [] }); + } - showLastAgent() { - this.props.tableProps.showAgent(this.lastAgent); - } + showLastAgent() { + this.props.tableProps.showAgent(this.lastAgent); + } - showMostActiveAgent() { - this.mostActiveAgent.name ? this.props.tableProps.showAgent(this.mostActiveAgent) : ''; - } + showMostActiveAgent() { + this.mostActiveAgent.name ? this.props.tableProps.showAgent(this.mostActiveAgent) : ''; + } - showAgentsWithFilters(filter) { - this._isMount && - this.setState({ - agentTableFilters: [{ field: 'q', value: `status=${filter}` }], - }); - } + showAgentsWithFilters(filter) { + this._isMount && + this.setState({ + agentTableFilters: [{ field: 'q', value: `status=${filter}` }], + }); + } - render() { - const colors = ['#017D73', '#bd271e', '#69707D']; - return ( - - - - {this.state.loading && ( - - - - ) || ( - - - - - {this.totalAgents > 0 && ( - - this._isMount && this.setState({ - agentTableFilters: [ {field: 'q', value: `status=${this.agentStatusLabelToID(status)}`}] - })} - width={300} - height={150} - data={this.state.data} - colors={colors} - /> - - )} - - - - {this.totalAgents > 0 && ( - - - - - {this.summary && ( - - - - this.showAgentsWithFilters(FILTER_ACTIVE)} >{this.state.data[0].value} - )} - titleSize={'s'} - description="Active" - titleColor="secondary" - className="white-space-nowrap" - /> - - - - this.showAgentsWithFilters(FILTER_DISCONNECTED)} >{this.state.data[1].value} - )} - titleSize={'s'} - description="Disconnected" - titleColor="danger" - className="white-space-nowrap" - /> - - - - this.showAgentsWithFilters(FILTER_NEVER_CONNECTED)} >{this.state.data[2].value} - )} - titleSize={'s'} - description="Never connected" - titleColor="subdued" - className="white-space-nowrap" - /> - - - - - - )} - - {this.lastAgent && ( - - - this.showLastAgent()}>{this.lastAgent.name} - } - titleSize="s" - description="Last registered agent" - titleColor="primary" - className="pb-12 white-space-nowrap" - /> - - )} - {this.mostActiveAgent && ( - - + + + {(this.state.loading && ( + + + + )) || ( + + + + + {this.totalAgents > 0 && ( + + + this._isMount && + this.setState({ + agentTableFilters: [ + { + field: 'q', + value: `status=${this.agentStatusLabelToID(status)}`, + }, + ], + }) } - title={ - - this.showMostActiveAgent()}>{this.mostActiveAgent.name || '-'} - } - className="white-space-nowrap" - titleSize="s" - description="Most active agent" - titleColor="primary" + width={300} + height={150} + data={this.state.data} + colors={colors} /> )} - - - - - )} - - )} - {this.state.showAgentsEvolutionVisualization && ( - - - + + + {this.totalAgents > 0 && ( -
- - - -
- {this.props.resultState === 'loading' && - ( -
- -
- ) } - + + + + {this.summary && ( + + + + this.showAgentsWithFilters(FILTER_ACTIVE)} + > + {this.state.data[0].value} + + + } + titleSize={'s'} + description="Active" + titleColor="secondary" + className="white-space-nowrap" + /> + + + + + this.showAgentsWithFilters(FILTER_DISCONNECTED) + } + > + {this.state.data[1].value} + + + } + titleSize={'s'} + description="Disconnected" + titleColor="danger" + className="white-space-nowrap" + /> + + + + + this.showAgentsWithFilters(FILTER_NEVER_CONNECTED) + } + > + {this.state.data[2].value} + + + } + titleSize={'s'} + description="Never connected" + titleColor="subdued" + className="white-space-nowrap" + /> + + + + + + )} + + {this.lastAgent && ( + + + this.showLastAgent()}> + {this.lastAgent.name} + + + } + titleSize="s" + description="Last registered agent" + titleColor="primary" + className="pb-12 white-space-nowrap" + /> + + )} + {this.mostActiveAgent && ( + + + this.showMostActiveAgent()}> + {this.mostActiveAgent.name || '-'} + + + } + className="white-space-nowrap" + titleSize="s" + description="Most active agent" + titleColor="primary" + /> + + )} + + + +
-
- - - No results found in the selected time range} - actions={ - { }} /> - } - /> - -
- - )} - - + )} + + )} + {this.state.showAgentsEvolutionVisualization && ( + + + + +
+ + + +
+ {this.props.resultState === 'loading' && ( +
+ +
+ )} +
+
+
+ + No results found in the selected time range} + actions={ {}} />} + /> + +
+ )} + + formatUIDate(date)} + formatUIDate={(date) => formatUIDate(date)} reload={() => this.getSummary()} /> - -
- ); + + + ); + } } -}); +); AgentsTable.propTypes = { tableProps: PropTypes.object, - showAgent: PropTypes.func + showAgent: PropTypes.func, }; diff --git a/public/controllers/agent/components/agents-table.js b/public/controllers/agent/components/agents-table.js index 1e1432b246..85ce6be84d 100644 --- a/public/controllers/agent/components/agents-table.js +++ b/public/controllers/agent/components/agents-table.js @@ -28,7 +28,7 @@ import { EuiCallOut, EuiOverlayMask, EuiConfirmModal, - EuiLoadingSpinner + EuiLoadingSpinner, } from '@elastic/eui'; import { CheckUpgrade } from './checkUpgrade'; import { getToasts } from '../../../kibana-services'; @@ -40,992 +40,1044 @@ import { WzSearchBar, filtersToObject } from '../../../components/wz-search-bar' import { getAgentFilterValues } from '../../../controllers/management/components/management/groups/get-agents-filters-values'; import { WzButtonPermissions } from '../../../components/common/permissions/button'; import { formatUIDate } from '../../../react-services/time-service'; -import { withErrorBoundary } from '../../../components/common/hocs' - -export const AgentsTable = withErrorBoundary (class AgentsTable extends Component { - _isMount = false; - constructor(props) { - super(props); - this.state = { - agents: [], - isLoading: false, - pageIndex: 0, - pageSize: 15, - sortDirection: 'asc', - sortField: 'id', - totalItems: 0, - selectedItems: [], - allSelected: false, - purgeModal: false, - filters: sessionStorage.getItem('agents_preview_selected_options') ? JSON.parse(sessionStorage.getItem('agents_preview_selected_options')) : [] - }; - this.suggestions = [ - { type: 'q', label: 'status', description: 'Filter by agent connection status', operators: ['=', '!=',], values: ['active', 'disconnected', 'never_connected', 'pending'] }, - { type: 'q', label: 'os.platform', description: 'Filter by OS platform', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('os.platform', value, { q: 'id!=000' }) }, - { type: 'q', label: 'ip', description: 'Filter by agent IP', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('ip', value, { q: 'id!=000' }) }, - { type: 'q', label: 'name', description: 'Filter by agent name', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('name', value, { q: 'id!=000' }) }, - { type: 'q', label: 'id', description: 'Filter by agent id', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('id', value, { q: 'id!=000' }) }, - { type: 'q', label: 'group', description: 'Filter by agent group', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('group', value, { q: 'id!=000' }) }, - { type: 'q', label: 'node_name', description: 'Filter by node name', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('node_name', value, { q: 'id!=000' }) }, - { type: 'q', label: 'manager', description: 'Filter by manager', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('manager', value, { q: 'id!=000' }) }, - { type: 'q', label: 'version', description: 'Filter by agent version', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('version', value, { q: 'id!=000' }) }, - { type: 'q', label: 'configSum', description: 'Filter by agent config sum', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('configSum', value, { q: 'id!=000' }) }, - { type: 'q', label: 'mergedSum', description: 'Filter by agent merged sum', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('mergedSum', value, { q: 'id!=000' }) }, - { type: 'q', label: 'dateAdd', description: 'Filter by add date', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('dateAdd', value, { q: 'id!=000' }) }, - { type: 'q', label: 'lastKeepAlive', description: 'Filter by last keep alive', operators: ['=', '!=',], values: async (value) => getAgentFilterValues('lastKeepAlive', value, { q: 'id!=000' }) }, - ]; - this.downloadCsv.bind(this); - } +import { withErrorBoundary } from '../../../components/common/hocs'; +import { UI_LOGGER_LEVELS } from '../../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../../react-services/common-services'; + +const errorContext = 'AgentsTable'; + +export const AgentsTable = withErrorBoundary( + class AgentsTable extends Component { + _isMount = false; + constructor(props) { + super(props); + this.state = { + agents: [], + isLoading: false, + pageIndex: 0, + pageSize: 15, + sortDirection: 'asc', + sortField: 'id', + totalItems: 0, + selectedItems: [], + allSelected: false, + purgeModal: false, + filters: sessionStorage.getItem('agents_preview_selected_options') + ? JSON.parse(sessionStorage.getItem('agents_preview_selected_options')) + : [], + }; + this.suggestions = [ + { + type: 'q', + label: 'status', + description: 'Filter by agent connection status', + operators: ['=', '!='], + values: ['active', 'disconnected', 'never_connected', 'pending'], + }, + { + type: 'q', + label: 'os.platform', + description: 'Filter by OS platform', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('os.platform', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'ip', + description: 'Filter by agent IP', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('ip', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'name', + description: 'Filter by agent name', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('name', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'id', + description: 'Filter by agent id', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('id', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'group', + description: 'Filter by agent group', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('group', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'node_name', + description: 'Filter by node name', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('node_name', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'manager', + description: 'Filter by manager', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('manager', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'version', + description: 'Filter by agent version', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('version', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'configSum', + description: 'Filter by agent config sum', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('configSum', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'mergedSum', + description: 'Filter by agent merged sum', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('mergedSum', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'dateAdd', + description: 'Filter by add date', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('dateAdd', value, { q: 'id!=000' }), + }, + { + type: 'q', + label: 'lastKeepAlive', + description: 'Filter by last keep alive', + operators: ['=', '!='], + values: async (value) => getAgentFilterValues('lastKeepAlive', value, { q: 'id!=000' }), + }, + ]; + this.downloadCsv.bind(this); + } - async UNSAFE_componentWillMount() { - const managerVersion = await WzRequest.apiReq('GET', '//', {}); - const totalAgent = await WzRequest.apiReq('GET', '/agents', {}); - const agentActive = await WzRequest.apiReq('GET', '/agents', { - params: { - q: 'status=active' - } - }); + async UNSAFE_componentWillMount() { + const managerVersion = await WzRequest.apiReq('GET', '//', {}); + const totalAgent = await WzRequest.apiReq('GET', '/agents', {}); + const agentActive = await WzRequest.apiReq('GET', '/agents', { + params: { + q: 'status=active', + }, + }); - this.setState({ - managerVersion: managerVersion.data.data.api_version, - agentActive: agentActive.data.data.totalItems, - avaibleAgents: totalAgent.data.data.affected_items - }); - } + this.setState({ + managerVersion: managerVersion.data.data.api_version, + agentActive: agentActive.data.data.totalItems, + avaibleAgents: totalAgent.data.data.affected_items, + }); + } - onTableChange = ({ page = {}, sort = {} }) => { - const { index: pageIndex, size: pageSize } = page; - const { field: sortField, direction: sortDirection } = sort; - this._isMount && this.setState({ - pageIndex, - pageSize, - sortField, - sortDirection - }); - }; - - async componentDidMount() { - this._isMount = true; - await this.getItems(); - } + onTableChange = ({ page = {}, sort = {} }) => { + const { index: pageIndex, size: pageSize } = page; + const { field: sortField, direction: sortDirection } = sort; + this._isMount && + this.setState({ + pageIndex, + pageSize, + sortField, + sortDirection, + }); + }; - componentWillUnmount() { - this._isMount = false; - if (sessionStorage.getItem('agents_preview_selected_options')) { - sessionStorage.removeItem('agents_preview_selected_options'); + async componentDidMount() { + this._isMount = true; + await this.getItems(); } - } - async reloadAgents() { - // const totalAgent = await WzRequest.apiReq('GET', '/agents', {}); - // this._isMount && this.setState({ - // isLoading: true, - // avaibleAgents: totalAgent.data.data.items - // }); - await this.getItems(); - await this.props.reload(); - } + componentWillUnmount() { + this._isMount = false; + if (sessionStorage.getItem('agents_preview_selected_options')) { + sessionStorage.removeItem('agents_preview_selected_options'); + } + } - async componentDidUpdate(prevProps, prevState) { - if (!(_.isEqual(prevState.filters, this.state.filters)) - || prevState.pageIndex !== this.state.pageIndex - || prevState.pageSize !== this.state.pageSize - || prevState.sortField !== this.state.sortField - || prevState.sortDirection !== this.state.sortDirection) { + async reloadAgents() { await this.getItems(); - } else if (!(_.isEqual(prevProps.filters, this.props.filters)) && this.props.filters && this.props.filters.length) { - this.setState({ filters: this.props.filters, pageIndex: 0 }); - this.props.removeFilters(); + await this.props.reload(); } - // if (prevState.allSelected === false && this.state.allSelected === true) { - // this._isMount && this.setState({ loadingAllItem: true }); - // this.getAllItems(); - // } - } - async getItems() { - try { - this._isMount && this.setState({ isLoading: true }); - const rawAgents = await this.props.wzReq( - 'GET', - '/agents', - { params: this.buildFilter() } - ); + async componentDidUpdate(prevProps, prevState) { + if ( + !_.isEqual(prevState.filters, this.state.filters) || + prevState.pageIndex !== this.state.pageIndex || + prevState.pageSize !== this.state.pageSize || + prevState.sortField !== this.state.sortField || + prevState.sortDirection !== this.state.sortDirection + ) { + await this.getItems(); + } else if ( + !_.isEqual(prevProps.filters, this.props.filters) && + this.props.filters && + this.props.filters.length + ) { + this.setState({ filters: this.props.filters, pageIndex: 0 }); + this.props.removeFilters(); + } + } - const formatedAgents = ( - ((rawAgents || {}).data || {}).data || {} - ).affected_items.map(this.formatAgent.bind(this)); + async getItems() { + try { + this._isMount && this.setState({ isLoading: true }); + const rawAgents = await this.props.wzReq('GET', '/agents', { params: this.buildFilter() }); - this._isMount && - this.setState({ - agents: formatedAgents, - totalItems: (((rawAgents || {}).data || {}).data || {}).total_affected_items, - isLoading: false - }); - } catch (error) { - this.setState({ isLoading: false }); + const formatedAgents = (((rawAgents || {}).data || {}).data || {}).affected_items.map( + this.formatAgent.bind(this) + ); + + this._isMount && + this.setState({ + agents: formatedAgents, + totalItems: (((rawAgents || {}).data || {}).data || {}).total_affected_items, + isLoading: false, + }); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Could not get the agents list`, + }, + }; + getErrorOrchestrator().handleError(options); + this.setState({ isLoading: false }); + } } - } - async getAllItems() { - const { pageIndex, pageSize } = this.state; - const filterTable = { - offset: pageIndex * pageSize, - limit: pageSize, - q: this.buildQFilter(), - sort: this.buildSortFilter() - }; + async getAllItems() { + const { pageIndex, pageSize } = this.state; + const filterTable = { + offset: pageIndex * pageSize, + limit: pageSize, + q: this.buildQFilter(), + sort: this.buildSortFilter(), + }; - const filterAll = { - q: this.buildQFilter(), - sort: this.buildSortFilter() - }; + const filterAll = { + q: this.buildQFilter(), + sort: this.buildSortFilter(), + }; - const rawAgents = await this.props.wzReq('GET', '/agents', filterTable); + const rawAgents = await this.props.wzReq('GET', '/agents', filterTable); - const agentsFiltered = await this.props - .wzReq('GET', '/agents', filterAll) - .then(() => { + const agentsFiltered = await this.props.wzReq('GET', '/agents', filterAll).then(() => { this._isMount && this.setState({ loadingAllItem: false }); }); - const formatedAgents = ( - ((rawAgents || {}).data || {}).data || {} - ).items.map(this.formatAgent.bind(this)); - this._isMount && - this.setState({ - agents: formatedAgents, - avaibleAgents: agentsFiltered.data.data.items, - totalItems: (((rawAgents || {}).data || {}).data || {}).totalItems, - isLoading: false - }); - } + const formatedAgents = (((rawAgents || {}).data || {}).data || {}).items.map( + this.formatAgent.bind(this) + ); + this._isMount && + this.setState({ + agents: formatedAgents, + avaibleAgents: agentsFiltered.data.data.items, + totalItems: (((rawAgents || {}).data || {}).data || {}).totalItems, + isLoading: false, + }); + } - buildFilter() { - const { pageIndex, pageSize, filters } = this.state; + buildFilter() { + const { pageIndex, pageSize, filters } = this.state; - const filter = { - ...filtersToObject(filters), - offset: (pageIndex * pageSize) || 0, - limit: pageSize, - sort: this.buildSortFilter() - }; - filter.q = !filter.q ? `id!=000` : `id!=000;${filter.q}`; + const filter = { + ...filtersToObject(filters), + offset: pageIndex * pageSize || 0, + limit: pageSize, + sort: this.buildSortFilter(), + }; + filter.q = !filter.q ? `id!=000` : `id!=000;${filter.q}`; - return filter; - } + return filter; + } - buildSortFilter() { - const { sortField, sortDirection } = this.state; + buildSortFilter() { + const { sortField, sortDirection } = this.state; - const field = sortField === 'os_name' ? 'os.name,os.version' : sortField; - const direction = sortDirection === 'asc' ? '+' : '-'; + const field = sortField === 'os_name' ? 'os.name,os.version' : sortField; + const direction = sortDirection === 'asc' ? '+' : '-'; - return direction + field; - } + return direction + field; + } - buildQFilter() { - const { q } = this.state; - return q === '' ? `id!=000` : `id!=000;${q}`; - } + buildQFilter() { + const { q } = this.state; + return q === '' ? `id!=000` : `id!=000;${q}`; + } - formatAgent(agent) { - const checkField = field => { - return field !== undefined ? field : '-'; - }; - const agentVersion = - agent.version !== undefined ? agent.version.split(' ')[1] : '-'; - const node_name = agent.node_name && agent.node_name !== 'unknown' ? agent.node_name : '-'; - - return { - id: agent.id, - name: agent.name, - ip: agent.ip, - status: agent.status, - group: checkField(agent.group), - os_name: agent, - version: agentVersion, - node_name: node_name, - dateAdd: agent.dateAdd ? formatUIDate(agent.dateAdd) : '-', - lastKeepAlive: agent.lastKeepAlive ? formatUIDate(agent.lastKeepAlive) : '-', - actions: agent, - upgrading: false - }; - } + formatAgent(agent) { + const checkField = (field) => { + return field !== undefined ? field : '-'; + }; + const agentVersion = agent.version !== undefined ? agent.version.split(' ')[1] : '-'; + const node_name = agent.node_name && agent.node_name !== 'unknown' ? agent.node_name : '-'; - actionButtonsRender(agent) { - return ( -
- - { - ev.stopPropagation(); - this.props.clickAction(agent, 'default'); - }} - iconType="eye" - color={'primary'} - aria-label="Open summary panel for this agent" - /> - -   - {agent.status !== 'never_connected' && - + return { + id: agent.id, + name: agent.name, + ip: agent.ip, + status: agent.status, + group: checkField(agent.group), + os_name: agent, + version: agentVersion, + node_name: node_name, + dateAdd: agent.dateAdd ? formatUIDate(agent.dateAdd) : '-', + lastKeepAlive: agent.lastKeepAlive ? formatUIDate(agent.lastKeepAlive) : '-', + actions: agent, + upgrading: false, + }; + } + + actionButtonsRender(agent) { + return ( +
+ { + onClick={(ev) => { ev.stopPropagation(); - this.props.clickAction(agent, 'configuration'); + this.props.clickAction(agent, 'default'); }} + iconType="eye" color={'primary'} - iconType="wrench" - aria-label="Open configuration for this agent" + aria-label="Open summary panel for this agent" /> +   + {agent.status !== 'never_connected' && ( + + { + ev.stopPropagation(); + this.props.clickAction(agent, 'configuration'); + }} + color={'primary'} + iconType="wrench" + aria-label="Open configuration for this agent" + /> + + )} +
+ ); + } + + addIconPlatformRender(agent) { + let icon = false; + const checkField = (field) => { + return field !== undefined ? field : '-'; + }; + const os = (agent || {}).os; + + if (((os || {}).uname || '').includes('Linux')) { + icon = 'linux'; + } else if ((os || {}).platform === 'windows') { + icon = 'windows'; + } else if ((os || {}).platform === 'darwin') { + icon = 'apple'; + } + const os_name = + checkField(((agent || {}).os || {}).name) + + ' ' + + checkField(((agent || {}).os || {}).version); + + return ( + + {' '} + {os_name === '- -' ? '-' : os_name} + + ); + } + + addHealthStatusRender(status) { + const color = (status) => { + if (status.toLowerCase() === 'active') { + return 'success'; + } else if (status.toLowerCase() === 'disconnected') { + return 'danger'; + } else if (status.toLowerCase() === 'never_connected') { + return 'subdued'; } -
- ); - } + }; + + return ( + + + {status === 'never_connected' ? 'never connected' : status} + + + ); + } - addIconPlatformRender(agent) { - let icon = false; - const checkField = field => { - return field !== undefined ? field : '-'; + reloadAgent = () => { + this._isMount && + this.setState({ + isLoading: true, + }); + this.props.reload(); }; - const os = (agent || {}).os; - - if (((os || {}).uname || '').includes('Linux')) { - icon = 'linux'; - } else if ((os || {}).platform === 'windows') { - icon = 'windows'; - } else if ((os || {}).platform === 'darwin') { - icon = 'apple'; + + addUpgradeStatus(version, agent) { + const { managerVersion } = this.state; + return ( + + ); } - const os_name = - checkField(((agent || {}).os || {}).name) + - ' ' + - checkField(((agent || {}).os || {}).version); - - return ( - - {' '} - {os_name === '- -' ? '-' : os_name} - - ); - } + downloadCsv = () => { + const filters = this.buildFilter(); + const formatedFilters = Object.keys(filters) + .filter((field) => !['limit', 'offset', 'sort'].includes(field)) + .map((field) => ({ name: field, value: filters[field] })); + this.props.downloadCsv(formatedFilters); + }; + formattedButton() { + return ( + + + Export formatted + + + ); + } - addHealthStatusRender(status) { - const color = status => { - if (status.toLowerCase() === 'active') { - return 'success'; - } else if (status.toLowerCase() === 'disconnected') { - return 'danger'; - } else if (status.toLowerCase() === 'never_connected') { - return 'subdued'; - } + showToast = (color, title, text, time) => { + getToasts().add({ + color: color, + title: title, + text: text, + toastLifeTimeMs: time, + }); }; - return {status === 'never_connected' ? 'never connected' : status}; - } + /* MULTISELECT TABLE */ + onSelectionChange = (selectedItems) => { + const { managerVersion, pageSize } = this.state; - reloadAgent = () => { - this._isMount && this.setState({ - isLoading: true - }); - this.props.reload(); - }; - - addUpgradeStatus(version, agent) { - const { managerVersion } = this.state; - return ( - - ); - } + selectedItems.forEach((item) => { + if (managerVersion > item.version && item.version !== '.') { + item.outdated = true; + } + }); - downloadCsv = () => { - const filters = this.buildFilter(); - const formatedFilters = Object.keys(filters) - .filter(field => !['limit', 'offset', 'sort'].includes(field)) - .map(field => ({ name: field, value: filters[field] })) - this.props.downloadCsv(formatedFilters); - }; - formattedButton() { - return ( - - - Export formatted - - - ); - } + selectedItems.length !== pageSize + ? this._isMount && this.setState({ allSelected: false }) + : false; - showToast = (color, title, text, time) => { - getToasts().add({ - color: color, - title: title, - text: text, - toastLifeTimeMs: time - }); - }; - - /* MULTISELECT TABLE */ - onSelectionChange = selectedItems => { - const { managerVersion, pageSize } = this.state; - - selectedItems.forEach(item => { - if (managerVersion > item.version && item.version !== '.') { - item.outdated = true; - } - }); - - selectedItems.length !== pageSize - ? this._isMount && this.setState({ allSelected: false }) - : false; - - this._isMount && this.setState({ selectedItems }); - }; - - renderUpgradeButton() { - const { selectedItems } = this.state; - - if ( - selectedItems.length === 0 || - (selectedItems.length > 0 && - selectedItems.filter(item => item.outdated).length === 0) || - (selectedItems.length > 0 && - selectedItems.filter(item => item.upgrading).length > 0) || - (selectedItems.length > 0 && - selectedItems.filter(item => item.status === 'Active').length === 0) || - (selectedItems.length > 0 && - selectedItems.filter(item => item.status === 'Active').length === 0 && - selectedItems.filter(item => item.status === 'Disconnected').length > - 0) || - selectedItems.filter(item => item.outdated && item.status === 'Active') - .length === 0 - ) { - return; - } + this._isMount && this.setState({ selectedItems }); + }; - return ( - - - Upgrade{' '} - { - selectedItems.filter( - item => item.outdated && item.status === 'Active' - ).length - }{' '} - agents - - - ); - } + renderUpgradeButton() { + const { selectedItems } = this.state; + + if ( + selectedItems.length === 0 || + (selectedItems.length > 0 && selectedItems.filter((item) => item.outdated).length === 0) || + (selectedItems.length > 0 && selectedItems.filter((item) => item.upgrading).length > 0) || + (selectedItems.length > 0 && + selectedItems.filter((item) => item.status === 'Active').length === 0) || + (selectedItems.length > 0 && + selectedItems.filter((item) => item.status === 'Active').length === 0 && + selectedItems.filter((item) => item.status === 'Disconnected').length > 0) || + selectedItems.filter((item) => item.outdated && item.status === 'Active').length === 0 + ) { + return; + } - renderUpgradeButtonAll() { - const { selectedItems, avaibleAgents, managerVersion } = this.state; - - if ( - selectedItems.length > 0 && - avaibleAgents.filter( - agent => - agent.version !== 'Wazuh ' + managerVersion && - agent.status === 'Active' - ).length === 0 - ) { - return; + return ( + + + Upgrade{' '} + {selectedItems.filter((item) => item.outdated && item.status === 'Active').length}{' '} + agents + + + ); } - return ( - - - Upgrade all agents - - - ); - } + renderUpgradeButtonAll() { + const { selectedItems, avaibleAgents, managerVersion } = this.state; - renderRestartButton() { - const { selectedItems } = this.state; + if ( + selectedItems.length > 0 && + avaibleAgents.filter( + (agent) => agent.version !== 'Wazuh ' + managerVersion && agent.status === 'Active' + ).length === 0 + ) { + return; + } - if ( - selectedItems.length === 0 || - selectedItems.filter(item => item.status === 'Active').length === 0 - ) { - return; + return ( + + + Upgrade all agents + + + ); } - return ( - - - Restart{' '} - {selectedItems.filter(item => item.status === 'Active').length} agents - - - ); - } + renderRestartButton() { + const { selectedItems } = this.state; - renderRestartButtonAll() { - const { selectedItems, agentActive, avaibleAgents } = this.state; + if ( + selectedItems.length === 0 || + selectedItems.filter((item) => item.status === 'Active').length === 0 + ) { + return; + } - if ( - (selectedItems.length > 0 && - avaibleAgents.filter(item => item.status === 'Active').length === 0 && - selectedItems.length === 0) || - agentActive === 0 - ) { - return; + return ( + + + Restart {selectedItems.filter((item) => item.status === 'Active').length} agents + + + ); } - return ( - - - Restart all agents - - - ); - } + renderRestartButtonAll() { + const { selectedItems, agentActive, avaibleAgents } = this.state; - renderPurgeButton() { - const { selectedItems } = this.state; + if ( + (selectedItems.length > 0 && + avaibleAgents.filter((item) => item.status === 'Active').length === 0 && + selectedItems.length === 0) || + agentActive === 0 + ) { + return; + } - if (selectedItems.length === 0) { - return; + return ( + + + Restart all agents + + + ); } - return ( - - { - this.setState({ purgeModal: true }); - }} - > - Delete {selectedItems.length} agents - - - ); - } + renderPurgeButton() { + const { selectedItems } = this.state; - renderPurgeButtonAll() { - const { selectedItems, allSelected } = this.state; + if (selectedItems.length === 0) { + return; + } - if (selectedItems.length === 0 && !allSelected) { - return; + return ( + + { + this.setState({ purgeModal: true }); + }} + > + Delete {selectedItems.length} agents + + + ); } - return ( - - { - this._isMount && this.setState({ purgeModal: true }); - }} - > - Delete all agents - - - ); - } + renderPurgeButtonAll() { + const { selectedItems, allSelected } = this.state; - callOutRender() { - const { selectedItems, pageSize, allSelected, totalItems } = this.state; + if (selectedItems.length === 0 && !allSelected) { + return; + } - if (selectedItems.length === 0) { - return; - } else if (selectedItems.length === pageSize) { return ( -
- - + { + this._isMount && this.setState({ purgeModal: true }); + }} > - - - { - this._isMount && this.setState(prevState => ({ - allSelected: !prevState.allSelected - })); - }} - > - {allSelected - ? `Clear all agents selection (${totalItems})` - : `Select all agents (${totalItems})`} - - - - - -
+ Delete all agents + + ); } - } - - setUpgradingState(agentID) { - const { agents } = this.state; - agents.forEach(element => { - element.id === agentID ? (element.upgrading = true) : false; - }); - this._isMount && this.setState({ agents }); - } - changeUpgradingState = agentID => { - const { agents } = this.state; - agents.forEach(element => { - element.id === agentID && element.upgrading === true - ? (element.upgrading = false) - : false; - }); - this._isMount && this.setState(() => ({ agents })); - }; - - onClickUpgrade = () => { - const { selectedItems } = this.state; - ActionAgents.upgradeAgents(selectedItems); - }; - - onClickUpgradeAll = () => { - const { avaibleAgents, managerVersion } = this.state; - ActionAgents.upgradeAllAgents(avaibleAgents, managerVersion); - }; - - onClickRestart = () => { - const { selectedItems } = this.state; - ActionAgents.restartAgents(selectedItems); - this.reloadAgents(); - }; - - onClickRestartAll = () => { - const { avaibleAgents } = this.state; - ActionAgents.restartAllAgents(avaibleAgents); - this.reloadAgents(); - }; - - onClickPurge = () => { - const { selectedItems } = this.state; - const auxAgents = selectedItems - .map(agent => { - return agent.id !== '000' ? agent.id : null; - }) - .filter(agent => agent !== null); - - WzRequest.apiReq('DELETE', `/agents`, { - purge: true, - ids: auxAgents, - older_than: '1s' - }) - .then(value => { - value.status === 200 - ? this.showToast( - 'success', - `Selected agents were successfully deleted`, - '', - 5000 - ) - : this.showToast( - 'warning', - `Failed to delete selected agents`, - '', - 5000 - ); - }) - .catch(error => { - this.showToast( - 'danger', - `Failed to delete selected agents`, - error, - 5000 + callOutRender() { + const { selectedItems, pageSize, allSelected, totalItems } = this.state; + + if (selectedItems.length === 0) { + return; + } else if (selectedItems.length === pageSize) { + return ( +
+ + + + + { + this._isMount && + this.setState((prevState) => ({ + allSelected: !prevState.allSelected, + })); + }} + > + {allSelected + ? `Clear all agents selection (${totalItems})` + : `Select all agents (${totalItems})`} + + + + + +
); - }) - .finally(() => { - this.getAllItems(); - this.reloadAgents(); + } + } + + setUpgradingState(agentID) { + const { agents } = this.state; + agents.forEach((element) => { + element.id === agentID ? (element.upgrading = true) : false; }); - this._isMount && this.setState({ purgeModal: false }); - }; - - onClickPurgeAll = () => { - const { avaibleAgents } = this.state; - const auxAgents = avaibleAgents - .map(agent => { - return agent.id !== '000' ? agent.id : null; - }) - .filter(agent => agent !== null); - - WzRequest.apiReq('DELETE', `/agents`, { - purge: true, - ids: auxAgents, - older_than: '1s' - }) - .then(value => { - value.status === 200 - ? this.showToast( - 'success', - `All agents have been successfully deleted`, - '', - 5000 - ) - : this.showToast('warning', `Failed to delete all agents`, '', 5000); - }) - .catch(error => { - this.showToast('danger', `Failed to delete all agents`, error, 5000); - }) - .finally(() => { - this.getAllItems(); - this.reloadAgents(); + this._isMount && this.setState({ agents }); + } + + changeUpgradingState = (agentID) => { + const { agents } = this.state; + agents.forEach((element) => { + element.id === agentID && element.upgrading === true ? (element.upgrading = false) : false; }); + this._isMount && this.setState(() => ({ agents })); + }; - this._isMount && this.setState({ purgeModal: false }); - }; - - columns() { - return [ - { - field: 'id', - name: 'ID', - sortable: true, - width: '6%' - }, - { - field: 'name', - name: 'Name', - sortable: true, - width: '15%', - truncateText: true - }, - { - field: 'ip', - name: 'IP', - width: '10%', - truncateText: true, - sortable: true - }, - { - field: 'group', - name: 'Group(s)', - width: '20%', - truncateText: true, - sortable: true, - render: groups => groups !== '-' ? this.renderGroups(groups) : '-' - }, - { - field: 'os_name', - name: 'OS', - sortable: true, - width: '15%', - truncateText: true, - render: this.addIconPlatformRender - }, - { - field: 'node_name', - name: 'Cluster node', - width: '10%', - truncateText: true, - sortable: true - }, - { - field: 'version', - name: 'Version', - width: '5%', - truncateText: true, - sortable: true - /* render: (version, agent) => this.addUpgradeStatus(version, agent), */ - }, - { - field: 'dateAdd', - name: 'Registration date', - width: '10%', - truncateText: true, - sortable: true - }, - { - field: 'lastKeepAlive', - name: 'Last keep alive', - width: '10%', - truncateText: true, - sortable: true - }, - { - field: 'status', - name: 'Status', - truncateText: true, - sortable: true, - width: '15%', - render: this.addHealthStatusRender - }, - { - align: 'right', - width: '5%', - field: 'actions', - name: 'Actions', - render: agent => this.actionButtonsRender(agent) - } - ]; - } + onClickUpgrade = () => { + const { selectedItems } = this.state; + ActionAgents.upgradeAgents(selectedItems); + }; - headRender() { - const formattedButton = this.formattedButton(); - return ( -
- - - - - {!!this.state.totalItems && ( - -

Agents ({this.state.totalItems})

-
- )} -
-
-
- - this.props.addingNewAgent()} - > - Deploy new agent - - - {formattedButton} -
- -
- ); - } + onClickUpgradeAll = () => { + const { avaibleAgents, managerVersion } = this.state; + ActionAgents.upgradeAllAgents(avaibleAgents, managerVersion); + }; - filterBarRender() { - return ( - - - this.setState({ filters, pageIndex: 0 })} - placeholder="Filter or search agent" - /> - - - this.reloadAgents()} - > - Refresh - - - - ); - } + onClickRestart = () => { + const { selectedItems } = this.state; + ActionAgents.restartAgents(selectedItems); + this.reloadAgents(); + }; - tableRender() { - const getRowProps = item => { - const { id } = item; - return { - 'data-test-subj': `row-${id}`, - className: 'customRowClass', - onClick: () => { } - }; + onClickRestartAll = () => { + const { avaibleAgents } = this.state; + ActionAgents.restartAllAgents(avaibleAgents); + this.reloadAgents(); }; - const getCellProps = (item, column) => { - if (column.field == "actions") { - return - } - return { - onMouseDown: (ev) => { - AppNavigate.navigateToModule(ev, 'agents', { "tab": "welcome", "agent": item.id, }); ev.stopPropagation() - } + onClickPurge = async () => { + const { selectedItems } = this.state; + const auxAgents = selectedItems + .map((agent) => { + return agent.id !== '000' ? agent.id : null; + }) + .filter((agent) => agent !== null); + try { + const response = await WzRequest.apiReq('DELETE', `/agents`, { + purge: true, + ids: auxAgents, + older_than: '1s', + }); + response.status === 200 + ? this.showToast('success', `Selected agents were successfully deleted`, '', 5000) + : this.showToast('warning', `Failed to delete selected agents`, '', 5000); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Failed to delete selected agents`, + }, + }; + getErrorOrchestrator().handleError(options); } + this.getAllItems(); + this.reloadAgents(); + this._isMount && this.setState({ purgeModal: false }); }; - const { - pageIndex, - pageSize, - totalItems, - agents, - sortField, - sortDirection, - isLoading - } = this.state; - const columns = this.columns(); - const pagination = - totalItems > 15 - ? { - pageIndex: pageIndex, - pageSize: pageSize, - totalItemCount: totalItems, - pageSizeOptions: [15, 25, 50, 100] - } - : false; - const sorting = { - sort: { - field: sortField, - direction: sortDirection + onClickPurgeAll = () => { + const { avaibleAgents } = this.state; + const auxAgents = avaibleAgents + .map((agent) => { + return agent.id !== '000' ? agent.id : null; + }) + .filter((agent) => agent !== null); + try { + const response = WzRequest.apiReq('DELETE', `/agents`, { + purge: true, + ids: auxAgents, + older_than: '1s', + }); + response.status === 200 + ? this.showToast('success', `All agents have been successfully deleted`, '', 5000) + : this.showToast('warning', `Failed to delete all agents`, '', 5000); + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + store: true, + error: { + error: error, + message: error.message || error, + title: `Failed to delete all agents`, + }, + }; + getErrorOrchestrator().handleError(options); } + this.getAllItems(); + this.reloadAgents(); + this._isMount && this.setState({ purgeModal: false }); }; - const selection = { - selectable: agent => agent.id, - /* onSelectionChange: this.onSelectionChange */ - }; + columns() { + return [ + { + field: 'id', + name: 'ID', + sortable: true, + width: '6%', + }, + { + field: 'name', + name: 'Name', + sortable: true, + width: '15%', + truncateText: true, + }, + { + field: 'ip', + name: 'IP', + width: '10%', + truncateText: true, + sortable: true, + }, + { + field: 'group', + name: 'Group(s)', + width: '20%', + truncateText: true, + sortable: true, + render: (groups) => (groups !== '-' ? this.renderGroups(groups) : '-'), + }, + { + field: 'os_name', + name: 'OS', + sortable: true, + width: '15%', + truncateText: true, + render: this.addIconPlatformRender, + }, + { + field: 'node_name', + name: 'Cluster node', + width: '10%', + truncateText: true, + sortable: true, + }, + { + field: 'version', + name: 'Version', + width: '5%', + truncateText: true, + sortable: true, + /* render: (version, agent) => this.addUpgradeStatus(version, agent), */ + }, + { + field: 'dateAdd', + name: 'Registration date', + width: '10%', + truncateText: true, + sortable: true, + }, + { + field: 'lastKeepAlive', + name: 'Last keep alive', + width: '10%', + truncateText: true, + sortable: true, + }, + { + field: 'status', + name: 'Status', + truncateText: true, + sortable: true, + width: '15%', + render: this.addHealthStatusRender, + }, + { + align: 'right', + width: '5%', + field: 'actions', + name: 'Actions', + render: (agent) => this.actionButtonsRender(agent), + }, + ]; + } - return ( - - - - - - ); - } + headRender() { + const formattedButton = this.formattedButton(); + return ( +
+ + + + + {!!this.state.totalItems && ( + +

Agents ({this.state.totalItems})

+
+ )} +
+
+
+ + this.props.addingNewAgent()} + > + Deploy new agent + + + {formattedButton} +
+ +
+ ); + } - filterGroupBadge = (group) => { - const { filters } = this.state; - let auxFilters = filters.map(filter => filter.value.match(/group=(.*S?)/)[1]); - if (filters.length > 0) { - !auxFilters.includes(group) ? - this.setState({ - filters: [...filters, { field: "q", value: `group=${group}` }], - }) : false; - } else { - this.setState({ - filters: [...filters, { field: "q", value: `group=${group}` }], - }) + filterBarRender() { + return ( + + + this.setState({ filters, pageIndex: 0 })} + placeholder="Filter or search agent" + /> + + + this.reloadAgents()}> + Refresh + + + + ); } - } - renderGroups(groups) { - return ( - - ) - } + tableRender() { + const getRowProps = (item) => { + const { id } = item; + return { + 'data-test-subj': `row-${id}`, + className: 'customRowClass', + onClick: () => {}, + }; + }; + + const getCellProps = (item, column) => { + if (column.field == 'actions') { + return; + } + return { + onMouseDown: (ev) => { + AppNavigate.navigateToModule(ev, 'agents', { tab: 'welcome', agent: item.id }); + ev.stopPropagation(); + }, + }; + }; - render() { - const { - allSelected, - purgeModal, - selectedItems, - loadingAllItem - } = this.state; - const title = this.headRender(); - const filter = this.filterBarRender(); - const upgradeButton = this.renderUpgradeButton(); - const restartButton = this.renderRestartButton(); - const purgeButton = this.renderPurgeButton(); - const upgradeButtonAll = this.renderUpgradeButtonAll(); - const restartButtonAll = this.renderRestartButtonAll(); - const purgeButtonAll = this.renderPurgeButtonAll(); - const table = this.tableRender(); - const callOut = this.callOutRender(); - let renderPurgeModal, loadItems, barButtons; - - if (purgeModal) { - renderPurgeModal = ( - - 15 + ? { + pageIndex: pageIndex, + pageSize: pageSize, + totalItemCount: totalItems, + pageSizeOptions: [15, 25, 50, 100], } - onCancel={() => { - this.setState({ purgeModal: false }); - }} - onConfirm={allSelected ? this.onClickPurgeAll : this.onClickPurge} - cancelButtonText="No, don't do it" - confirmButtonText="Yes, delete agents" - defaultFocusedButton="confirm" - buttonColor="danger" - > -

Are you sure you want to do this?

-
-
- ); - } + : false; + const sorting = { + sort: { + field: sortField, + direction: sortDirection, + }, + }; + + const selection = { + selectable: (agent) => agent.id, + /* onSelectionChange: this.onSelectionChange */ + }; - if (loadingAllItem) { - barButtons = ( + return ( - + ); - } else { - barButtons = ( - - {allSelected ? upgradeButtonAll : upgradeButton} - {allSelected ? restartButtonAll : restartButton} - {allSelected ? purgeButtonAll : purgeButton} - + } + + filterGroupBadge = (group) => { + const { filters } = this.state; + let auxFilters = filters.map((filter) => filter.value.match(/group=(.*S?)/)[1]); + if (filters.length > 0) { + !auxFilters.includes(group) + ? this.setState({ + filters: [...filters, { field: 'q', value: `group=${group}` }], + }) + : false; + } else { + this.setState({ + filters: [...filters, { field: 'q', value: `group=${group}` }], + }); + } + }; + + renderGroups(groups) { + return ( + ); } - return ( -
- {filter} - - - {title} - {loadItems} - {selectedItems.length > 0 && barButtons} - {callOut} - {table} - {renderPurgeModal} - -
- ); + render() { + const { allSelected, purgeModal, selectedItems, loadingAllItem } = this.state; + const title = this.headRender(); + const filter = this.filterBarRender(); + const upgradeButton = this.renderUpgradeButton(); + const restartButton = this.renderRestartButton(); + const purgeButton = this.renderPurgeButton(); + const upgradeButtonAll = this.renderUpgradeButtonAll(); + const restartButtonAll = this.renderRestartButtonAll(); + const purgeButtonAll = this.renderPurgeButtonAll(); + const table = this.tableRender(); + const callOut = this.callOutRender(); + let renderPurgeModal, loadItems, barButtons; + + if (purgeModal) { + renderPurgeModal = ( + + { + this.setState({ purgeModal: false }); + }} + onConfirm={allSelected ? this.onClickPurgeAll : this.onClickPurge} + cancelButtonText="No, don't do it" + confirmButtonText="Yes, delete agents" + defaultFocusedButton="confirm" + buttonColor="danger" + > +

Are you sure you want to do this?

+
+
+ ); + } + + if (loadingAllItem) { + barButtons = ( + + + + + + ); + } else { + barButtons = ( + + {allSelected ? upgradeButtonAll : upgradeButton} + {allSelected ? restartButtonAll : restartButton} + {allSelected ? purgeButtonAll : purgeButton} + + ); + } + + return ( +
+ {filter} + + + {title} + {loadItems} + {selectedItems.length > 0 && barButtons} + {callOut} + {table} + {renderPurgeModal} + +
+ ); + } } -}); +); AgentsTable.propTypes = { wzReq: PropTypes.func, @@ -1033,5 +1085,5 @@ AgentsTable.propTypes = { downloadCsv: PropTypes.func, clickAction: PropTypes.func, timeService: PropTypes.func, - reload: PropTypes.func + reload: PropTypes.func, }; diff --git a/public/controllers/agent/components/checkUpgrade.tsx b/public/controllers/agent/components/checkUpgrade.tsx index 66988a5efc..cff82809f9 100644 --- a/public/controllers/agent/components/checkUpgrade.tsx +++ b/public/controllers/agent/components/checkUpgrade.tsx @@ -11,78 +11,90 @@ */ import React, { Component } from 'react'; -import { - EuiLoadingSpinner, - EuiToolTip -} from '@elastic/eui'; +import { EuiLoadingSpinner, EuiToolTip } from '@elastic/eui'; import { WzRequest } from '../../../react-services/wz-request'; +import { UI_LOGGER_LEVELS } from '../../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../../react-services/common-services'; + +const errorContext = 'CheckUpgrade'; export class CheckUpgrade extends Component { - props!: { - id: String, - version: String - agent: Object, - upgrading: Boolean, - managerVersion: String, - changeStatusUpdate: Function, - reloadAgent: Function, - }; - interval: any; + props!: { + id: String; + version: String; + agent: Object; + upgrading: Boolean; + managerVersion: String; + changeStatusUpdate: Function; + reloadAgent: Function; + }; + interval: any; - constructor(props) { - super(props); - } + constructor(props) { + super(props); + } - componentWillUnmount() { - clearInterval(this.interval); - } + componentWillUnmount() { + clearInterval(this.interval); + } - componentDidUpdate(prevProps) { - if (prevProps.upgrading !== this.props.upgrading) { - if (this.props.upgrading === true) - this.interval = setInterval(() => this.checkUpgrade(this.props.id), 3000); - } - } + componentDidUpdate(prevProps) { + if (prevProps.upgrading !== this.props.upgrading) { + if (this.props.upgrading === true) + this.interval = setInterval(() => this.checkUpgrade(this.props.id), 3000); + } + } - checkUpgrade(agentId) { - WzRequest.apiReq('GET', `/agents/${agentId}/upgrade_result`, {}).then(value => { - if (value.status === 200) { - this.props.changeStatusUpdate(agentId); - this.props.reloadAgent(); - clearInterval(this.interval); - console.log(`${this.props.id} agente termina intervalo`); - } - }) - .catch((error) => { - console.log(error); - }); - }; + async checkUpgrade(agentId) { + try { + const response = await WzRequest.apiReq('GET', `/agents/${agentId}/upgrade_result`, {}); + if (response.data === 200) { + this.props.changeStatusUpdate(agentId); + this.props.reloadAgent(); + clearInterval(this.interval); + console.log(`${this.props.id} agent ends interval`); + } + } catch (error) { + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + error: { + error: error, + message: error.message || error, + title: error.message || error, + }, + }; + getErrorOrchestrator().handleError(options); + } + } - addUpgraingProgress() { - const { id, version, upgrading, managerVersion } = this.props; + addUpgraingProgress() { + const { id, version, upgrading, managerVersion } = this.props; - if (version === '.' || version === managerVersion) { - return; - } else if (upgrading === true) { - /* this.interval = setInterval(() => this.checkUpgrade(id), 30000); */ - return ( - - - - ) - } - }; + if (version === '.' || version === managerVersion) { + return; + } else if (upgrading === true) { + /* this.interval = setInterval(() => this.checkUpgrade(id), 30000); */ + return ( + + + + ); + } + } - render() { - const { version } = this.props; - let upgrading = this.addUpgraingProgress(); + render() { + const { version } = this.props; + let upgrading = this.addUpgraingProgress(); - return ( -
- {version} -   - {upgrading} -
- ) - } -} \ No newline at end of file + return ( +
+ {version} +   + {upgrading} +
+ ); + } +} diff --git a/public/controllers/agent/components/register-agent.js b/public/controllers/agent/components/register-agent.js index 1abd76464c..f3156e712a 100644 --- a/public/controllers/agent/components/register-agent.js +++ b/public/controllers/agent/components/register-agent.js @@ -33,680 +33,722 @@ import { EuiSpacer, EuiProgress, EuiCode, - EuiLink + EuiLink, } from '@elastic/eui'; import { WzRequest } from '../../../react-services/wz-request'; -import { withErrorBoundary } from '../../../components/common/hocs' +import { withErrorBoundary } from '../../../components/common/hocs'; +import { UI_LOGGER_LEVELS } from '../../../../common/constants'; +import { UI_ERROR_SEVERITIES } from '../../../react-services/error-orchestrator/types'; +import { getErrorOrchestrator } from '../../../react-services/common-services'; + +const errorContext = 'RegisterAgent'; const architectureButtons = [ { id: 'i386', - label: 'i386' + label: 'i386', }, { id: 'x86_64', - label: 'x86_64' + label: 'x86_64', }, { id: 'armhf', - label: 'armhf' + label: 'armhf', }, { id: 'aarch64', - label: 'aarch64' - } + label: 'aarch64', + }, ]; const architectureCentos5 = [ { id: 'i386', - label: 'i386' + label: 'i386', }, { id: 'x86_64', - label: 'x86_64' - } + label: 'x86_64', + }, ]; const versionButtonsCentos = [ { id: 'centos5', - label: 'CentOS5' + label: 'CentOS5', }, { id: 'centos6', - label: 'CentOS6 or higher' - } + label: 'CentOS6 or higher', + }, ]; const osButtons = [ { id: 'rpm', - label: 'Red Hat / CentOS' + label: 'Red Hat / CentOS', }, { id: 'deb', - label: 'Debian / Ubuntu' + label: 'Debian / Ubuntu', }, { id: 'win', - label: 'Windows' + label: 'Windows', }, { id: 'macos', - label: 'MacOS' - } + label: 'MacOS', + }, ]; const sysButtons = [ { id: 'systemd', - label: 'Systemd' + label: 'Systemd', }, { id: 'sysV', - label: 'SysV Init' - } + label: 'SysV Init', + }, ]; const pTextCheckConnectionStyle = { marginTop: '3em', }; -export const RegisterAgent = withErrorBoundary (class RegisterAgent extends Component { - constructor(props) { - super(props); - this.wazuhConfig = new WazuhConfig(); - this.configuration = this.wazuhConfig.getConfig(); - this.state = { - status: 'incomplete', - selectedOS: '', - selectedSYS: '', - neededSYS: false, - selectedArchitecture: '', - selectedVersion: '', - version: '', - wazuhVersion: '', - serverAddress: '', - wazuhPassword: '', - groups: [], - selectedGroup: [], - udpProtocol: false, - }; - this.restartAgentCommand = { - rpm: this.systemSelector(), - deb: this.systemSelector(), - macos: 'sudo /Library/Ossec/bin/wazuh-control start', - }; - } +export const RegisterAgent = withErrorBoundary( + class RegisterAgent extends Component { + constructor(props) { + super(props); + this.wazuhConfig = new WazuhConfig(); + this.configuration = this.wazuhConfig.getConfig(); + this.state = { + status: 'incomplete', + selectedOS: '', + selectedSYS: '', + neededSYS: false, + selectedArchitecture: '', + selectedVersion: '', + version: '', + wazuhVersion: '', + serverAddress: '', + wazuhPassword: '', + groups: [], + selectedGroup: [], + udpProtocol: false, + }; + this.restartAgentCommand = { + rpm: this.systemSelector(), + deb: this.systemSelector(), + macos: 'sudo /Library/Ossec/bin/wazuh-control start', + }; + } - async componentDidMount() { - try { - this.setState({ loading: true }); - const wazuhVersion = await this.props.getWazuhVersion(); - let serverAddress = false; - let wazuhPassword = ''; - let hidePasswordInput = false; - serverAddress = this.configuration['enrollment.dns'] || false; - if (!serverAddress) { - serverAddress = await this.props.getCurrentApiAddress(); - } - let authInfo = await this.getAuthInfo(); - const needsPassword = (authInfo.auth || {}).use_password === 'yes'; - if (needsPassword) { - wazuhPassword = this.configuration['enrollment.password'] || authInfo['authd.pass'] || ''; - if (wazuhPassword) { - hidePasswordInput = true; + async componentDidMount() { + try { + this.setState({ loading: true }); + const wazuhVersion = await this.props.getWazuhVersion(); + let serverAddress = false; + let wazuhPassword = ''; + let hidePasswordInput = false; + serverAddress = this.configuration['enrollment.dns'] || false; + if (!serverAddress) { + serverAddress = await this.props.getCurrentApiAddress(); + } + let authInfo = await this.getAuthInfo(); + const needsPassword = (authInfo.auth || {}).use_password === 'yes'; + if (needsPassword) { + wazuhPassword = this.configuration['enrollment.password'] || authInfo['authd.pass'] || ''; + if (wazuhPassword) { + hidePasswordInput = true; + } } - } - const udpProtocol = await this.getRemoteInfo(); - const groups = await this.getGroups(); - this.setState({ - serverAddress, - needsPassword, - hidePasswordInput, - versionButtonsCentos, - architectureButtons, - architectureCentos5, - wazuhPassword, - udpProtocol, - wazuhVersion, - groups, - loading: false, - }); - } catch (error) { - this.setState({ - wazuhVersion: version, - loading: false, - }); + const udpProtocol = await this.getRemoteInfo(); + const groups = await this.getGroups(); + this.setState({ + serverAddress, + needsPassword, + hidePasswordInput, + versionButtonsCentos, + architectureButtons, + architectureCentos5, + wazuhPassword, + udpProtocol, + wazuhVersion, + groups, + loading: false, + }); + } catch (error) { + this.setState({ + wazuhVersion: version, + loading: false, + }); + const options = { + context: errorContext, + level: UI_LOGGER_LEVELS.ERROR, + severity: UI_ERROR_SEVERITIES.BUSINESS, + display: false, + store: false, + error: { + error: error, + message: error.message || error, + title: error.name || error, + }, + }; + getErrorOrchestrator().handleError(options); + } } - } - async getAuthInfo() { - try { - const result = await WzRequest.apiReq('GET', '/agents/000/config/auth/auth', {}); - return (result.data || {}).data || {}; - } catch (error) { - return false; + async getAuthInfo() { + try { + const result = await WzRequest.apiReq('GET', '/agents/000/config/auth/auth', {}); + return (result.data || {}).data || {}; + } catch (error) { + throw new Error(error); + } } - } - async getRemoteInfo() { - try { - const result = await WzRequest.apiReq('GET', '/agents/000/config/request/remote', {}); - const remote = ((result.data || {}).data || {}).remote || {}; - return (remote[0] || {}).protocol !== 'tcp' && (remote[0] || {}).protocol[0] !== 'TCP'; - } catch (error) { - return false; + async getRemoteInfo() { + try { + const result = await WzRequest.apiReq('GET', '/agents/000/config/request/remote', {}); + const remote = ((result.data || {}).data || {}).remote || {}; + return (remote[0] || {}).protocol !== 'tcp' && (remote[0] || {}).protocol[0] !== 'TCP'; + } catch (error) { + throw new Error(error); + } } - } - - selectOS(os) { - this.setState({ - selectedOS: os, - selectedVersion: '', - selectedArchitecture: '', - selectedSYS: 'systemd', - }); - } - - systemSelector() { - if (this.state.selectedOS === 'rpm') { - if (this.state.selectedSYS === 'systemd') { - return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent'; - } else return 'sudo chkconfig --add wazuh-agent\nsudo service wazuh-agent start'; - } else if (this.state.selectedOS === 'deb') { - if (this.state.selectedSYS === 'systemd') { - return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent'; - } else return 'sudo update-rc.d wazuh-agent defaults 95 10\nsudo service wazuh-agent start'; - } else return ''; - } - - selectSYS(sys) { - this.setState({ selectedSYS: sys }); - } - - setServerAddress(event) { - this.setState({ serverAddress: event.target.value }); - } - setGroupName(selectedGroup) { - this.setState({ selectedGroup }); - } - - setArchitecture(selectedArchitecture) { - this.setState({ selectedArchitecture }); - } - - setVersion(selectedVersion) { - this.setState({ selectedVersion, selectedArchitecture: '' }); - } + selectOS(os) { + this.setState({ + selectedOS: os, + selectedVersion: '', + selectedArchitecture: '', + selectedSYS: 'systemd', + }); + } - setWazuhPassword(event) { - this.setState({ wazuhPassword: event.target.value }); - } + systemSelector() { + if (this.state.selectedOS === 'rpm') { + if (this.state.selectedSYS === 'systemd') { + return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent'; + } else return 'sudo chkconfig --add wazuh-agent\nsudo service wazuh-agent start'; + } else if (this.state.selectedOS === 'deb') { + if (this.state.selectedSYS === 'systemd') { + return 'sudo systemctl daemon-reload\nsudo systemctl enable wazuh-agent\nsudo systemctl start wazuh-agent'; + } else return 'sudo update-rc.d wazuh-agent defaults 95 10\nsudo service wazuh-agent start'; + } else return ''; + } - obfuscatePassword(text) { - let obfuscate = ''; - const regex = /WAZUH_REGISTRATION_PASSWORD=?\040?\'(.*?)\'/gm; - const match = regex.exec(text); - const password = match[1]; - if (password) { - [...password].forEach(() => (obfuscate += '*')); - text = text.replace(password, obfuscate); + selectSYS(sys) { + this.setState({ selectedSYS: sys }); } - return text; - } - async getGroups() { - try { - const result = await WzRequest.apiReq('GET', '/groups', {}); - return result.data.data.affected_items.map((item) => ({ label: item.name, id: item.name })); - } catch (error) { - return []; + setServerAddress(event) { + this.setState({ serverAddress: event.target.value }); } - } - optionalDeploymentVariables() { - let deployment = `WAZUH_MANAGER='${this.state.serverAddress}' `; + setGroupName(selectedGroup) { + this.setState({ selectedGroup }); + } - if (this.state.selectedOS == 'win') { - deployment += `WAZUH_REGISTRATION_SERVER='${this.state.serverAddress}' `; + setArchitecture(selectedArchitecture) { + this.setState({ selectedArchitecture }); } - if (this.state.needsPassword) { - deployment += `WAZUH_REGISTRATION_PASSWORD='${this.state.wazuhPassword}' `; + setVersion(selectedVersion) { + this.setState({ selectedVersion, selectedArchitecture: '' }); } - if (this.state.udpProtocol) { - deployment += `WAZUH_PROTOCOL='UDP' `; + setWazuhPassword(event) { + this.setState({ wazuhPassword: event.target.value }); } - if (this.state.selectedGroup.length) { - deployment += `WAZUH_AGENT_GROUP='${this.state.selectedGroup.map((item) => item.label).join(',')}' `; + obfuscatePassword(text) { + let obfuscate = ''; + const regex = /WAZUH_REGISTRATION_PASSWORD=?\040?\'(.*?)\'/gm; + const match = regex.exec(text); + const password = match[1]; + if (password) { + [...password].forEach(() => (obfuscate += '*')); + text = text.replace(password, obfuscate); + } + return text; } - // macos doesnt need = param - if (this.state.selectedOS === 'macos') { - return deployment.replace(/=/g, ' '); + async getGroups() { + try { + const result = await WzRequest.apiReq('GET', '/groups', {}); + return result.data.data.affected_items.map((item) => ({ label: item.name, id: item.name })); + } catch (error) { + throw new Error(error); + } } - return deployment; - } + optionalDeploymentVariables() { + let deployment = `WAZUH_MANAGER='${this.state.serverAddress}' `; + + if (this.state.selectedOS == 'win') { + deployment += `WAZUH_REGISTRATION_SERVER='${this.state.serverAddress}' `; + } + + if (this.state.needsPassword) { + deployment += `WAZUH_REGISTRATION_PASSWORD='${this.state.wazuhPassword}' `; + } + if (this.state.udpProtocol) { + deployment += `WAZUH_PROTOCOL='UDP' `; + } + + if (this.state.selectedGroup.length) { + deployment += `WAZUH_AGENT_GROUP='${this.state.selectedGroup + .map((item) => item.label) + .join(',')}' `; + } - resolveRPMPackage() { - switch (`${this.state.selectedVersion}-${this.state.selectedArchitecture}`) { - case 'centos5-i386': - return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}-1.el5.i386.rpm`; - case 'centos5-x86_64': - return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.el5.x86_64.rpm`; - case 'centos6-i386': - return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.i386.rpm`; - case 'centos6-aarch64': - return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.aarch64.rpm`; - case 'centos6-x86_64': - return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; - case 'centos6-armhf': - return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.armv7hl.rpm`; - default: - return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; + // macos doesnt need = param + if (this.state.selectedOS === 'macos') { + return deployment.replace(/=/g, ' '); + } + + return deployment; } - } - resolveDEBPackage() { - switch (`${this.state.selectedArchitecture}`) { - case 'i386': - return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_i386.deb`; - case 'aarch64': - return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_arm64.deb`; - case 'armhf': - return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_armhf.deb`; - case 'x86_64': - return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`; - default: - return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`; + resolveRPMPackage() { + switch (`${this.state.selectedVersion}-${this.state.selectedArchitecture}`) { + case 'centos5-i386': + return `https://packages.wazuh.com/4.x/yum5/i386/wazuh-agent-${this.state.wazuhVersion}-1.el5.i386.rpm`; + case 'centos5-x86_64': + return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.el5.x86_64.rpm`; + case 'centos6-i386': + return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.i386.rpm`; + case 'centos6-aarch64': + return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.aarch64.rpm`; + case 'centos6-x86_64': + return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; + case 'centos6-armhf': + return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.armv7hl.rpm`; + default: + return `https://packages.wazuh.com/4.x/yum/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; + } } - } - optionalPackages() { - switch (this.state.selectedOS) { - case 'rpm': - return this.resolveRPMPackage(); - case 'deb': - return this.resolveDEBPackage(); - default: - return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; + resolveDEBPackage() { + switch (`${this.state.selectedArchitecture}`) { + case 'i386': + return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_i386.deb`; + case 'aarch64': + return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_arm64.deb`; + case 'armhf': + return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_armhf.deb`; + case 'x86_64': + return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`; + default: + return `https://packages.wazuh.com/4.x/apt/pool/main/w/wazuh-agent/wazuh-agent_${this.state.wazuhVersion}-1_amd64.deb`; + } } - } - checkMissingOSSelection() { - if (!this.state.selectedOS) { - return ['Operating system']; + optionalPackages() { + switch (this.state.selectedOS) { + case 'rpm': + return this.resolveRPMPackage(); + case 'deb': + return this.resolveDEBPackage(); + default: + return `https://packages.wazuh.com/4.x/yum5/x86_64/wazuh-agent-${this.state.wazuhVersion}-1.x86_64.rpm`; + } } - switch (this.state.selectedOS) { - case 'rpm': - return [ - ...(!this.state.selectedVersion ? ['OS version'] : []), - ...(this.state.selectedVersion && !this.state.selectedArchitecture - ? ['OS architecture'] - : []), - ]; - case 'deb': - return [...(!this.state.selectedArchitecture ? ['OS architecture'] : [])]; - default: - return []; + + checkMissingOSSelection() { + if (!this.state.selectedOS) { + return ['Operating system']; + } + switch (this.state.selectedOS) { + case 'rpm': + return [ + ...(!this.state.selectedVersion ? ['OS version'] : []), + ...(this.state.selectedVersion && !this.state.selectedArchitecture + ? ['OS architecture'] + : []), + ]; + case 'deb': + return [...(!this.state.selectedArchitecture ? ['OS architecture'] : [])]; + default: + return []; + } } - } - render() { - const appVersionMajorDotMinor = this.state.wazuhVersion.split('.').slice(0, 2).join('.'); - const urlCheckConnectionDocumentation = `https://documentation.wazuh.com/${appVersionMajorDotMinor}/user-manual/agents/agent-connection.html`; - const textAndLinkToCheckConnectionDocumentation = ( -

- To verify the connection with the Manager, please follow this{' '} - - document. - -

- ); - const missingOSSelection = this.checkMissingOSSelection(); - const ipInput = ( - -

- You can predefine the Wazuh server address with the enrollment.dns{' '} - Wazuh app setting. + render() { + const appVersionMajorDotMinor = this.state.wazuhVersion.split('.').slice(0, 2).join('.'); + const urlCheckConnectionDocumentation = `https://documentation.wazuh.com/${appVersionMajorDotMinor}/user-manual/agents/agent-connection.html`; + const textAndLinkToCheckConnectionDocumentation = ( +

+ To verify the connection with the Manager, please follow this{' '} + + document. +

+ ); + const missingOSSelection = this.checkMissingOSSelection(); + const ipInput = ( + +

+ You can predefine the Wazuh server address with the enrollment.dns{' '} + Wazuh app setting. +

+ this.setServerAddress(event)} + /> +
+ ); + + const groupInput = ( + +

Select one or more existing groups

+ { + this.setGroupName(group); + }} + isDisabled={!this.state.groups.length} + isClearable={true} + data-test-subj="demoComboBox" + /> +
+ ); + + const passwordInput = ( this.setServerAddress(event)} + placeholder="Wazuh password" + value={this.state.wazuhPassword} + onChange={(event) => this.setWazuhPassword(event)} /> -
- ); - - const groupInput = ( - -

Select one or more existing groups

- { - this.setGroupName(group); - }} - isDisabled={!this.state.groups.length} - isClearable={true} - data-test-subj="demoComboBox" - /> -
- ); - - const passwordInput = ( - this.setWazuhPassword(event)} - /> - ); - - const codeBlock = { - zIndex: '100', - }; - const customTexts = { - rpmText: `sudo ${this.optionalDeploymentVariables()}yum install ${this.optionalPackages()}`, - debText: `curl -so wazuh-agent-${this.state.wazuhVersion}.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}dpkg -i ./wazuh-agent-${this.state.wazuhVersion}.deb`, - macosText: `curl -so wazuh-agent-${this.state.wazuhVersion}.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-${ - this.state.wazuhVersion - }-1.pkg && sudo launchctl setenv ${this.optionalDeploymentVariables()}&& sudo installer -pkg ./wazuh-agent-${this.state.wazuhVersion}.pkg -target /`, - winText: `Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-${ - this.state.wazuhVersion - }-1.msi -OutFile wazuh-agent-${this.state.wazuhVersion}.msi; ./wazuh-agent-${this.state.wazuhVersion}.msi /q ${this.optionalDeploymentVariables()}`, - }; - - const field = `${this.state.selectedOS}Text`; - const text = customTexts[field]; - const language = this.state.selectedOS === 'win' ? 'ps' : 'bash'; - const windowsAdvice = this.state.selectedOS === 'win' && ( - <> - - - - ); - const restartAgentCommand = this.restartAgentCommand[this.state.selectedOS]; - const onTabClick = (selectedTab) => { - this.selectSYS(selectedTab.id); - }; - - const guide = ( -
- {this.state.selectedOS && ( - -

You can use this command to install and enroll the Wazuh agent in one or more hosts.

- Running this command on a host with an agent already installed upgrades the agent package without enrolling the agent. To enroll it, see the Wazuh documentation.} - iconType="iInCircle" - /> - - - {this.state.wazuhPassword ? this.obfuscatePassword(text) : text} - - {windowsAdvice} - - {(copy) => ( - - Copy command - - )} - -
- )} -
- ); - - const tabs = [ - { - id: 'systemd', - name: 'Systemd', - content: ( - - - - - {this.systemSelector()} - - - {(copy) => ( - - Copy command - - )} - - {textAndLinkToCheckConnectionDocumentation} - - - ), - }, - { - id: 'sysV', - name: 'SysV Init', - content: ( - - + ); + + const codeBlock = { + zIndex: '100', + }; + const customTexts = { + rpmText: `sudo ${this.optionalDeploymentVariables()}yum install ${this.optionalPackages()}`, + debText: `curl -so wazuh-agent-${ + this.state.wazuhVersion + }.deb ${this.optionalPackages()} && sudo ${this.optionalDeploymentVariables()}dpkg -i ./wazuh-agent-${ + this.state.wazuhVersion + }.deb`, + macosText: `curl -so wazuh-agent-${ + this.state.wazuhVersion + }.pkg https://packages.wazuh.com/4.x/macos/wazuh-agent-${ + this.state.wazuhVersion + }-1.pkg && sudo launchctl setenv ${this.optionalDeploymentVariables()}&& sudo installer -pkg ./wazuh-agent-${ + this.state.wazuhVersion + }.pkg -target /`, + winText: `Invoke-WebRequest -Uri https://packages.wazuh.com/4.x/windows/wazuh-agent-${ + this.state.wazuhVersion + }-1.msi -OutFile wazuh-agent-${this.state.wazuhVersion}.msi; ./wazuh-agent-${ + this.state.wazuhVersion + }.msi /q ${this.optionalDeploymentVariables()}`, + }; + + const field = `${this.state.selectedOS}Text`; + const text = customTexts[field]; + const language = this.state.selectedOS === 'win' ? 'ps' : 'bash'; + const windowsAdvice = this.state.selectedOS === 'win' && ( + <> + + + + ); + const restartAgentCommand = this.restartAgentCommand[this.state.selectedOS]; + const onTabClick = (selectedTab) => { + this.selectSYS(selectedTab.id); + }; + + const guide = ( +
+ {this.state.selectedOS && ( +

+ You can use this command to install and enroll the Wazuh agent in one or more hosts. +

+ + Running this command on a host with an agent already installed upgrades the + agent package without enrolling the agent. To enroll it, see the{' '} + + Wazuh documentation + + . + + } + iconType="iInCircle" + /> + - {this.systemSelector()} + {this.state.wazuhPassword ? this.obfuscatePassword(text) : text} - + {windowsAdvice} + {(copy) => ( Copy command )} - {textAndLinkToCheckConnectionDocumentation}
- - ), - }, - ]; - - const steps = [ - { - title: 'Choose the Operating system', - children: ( - this.selectOS(os)} - /> - ), - }, - ...(this.state.selectedOS == 'rpm' - ? [ - { - title: 'Choose the version', - children: ( - this.setVersion(version)} - /> - ), - }, - ] - : []), - ...(this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos5' - ? [ - { - title: 'Choose the architecture', - children: ( - this.setArchitecture(architecture)} - /> - ), - }, - ] - : []), - ...(this.state.selectedOS == 'deb' || - (this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos6') - ? [ - { - title: 'Choose the architecture', - children: ( - this.setArchitecture(architecture)} - /> - ), - }, - ] - : []), - { - title: 'Wazuh server address', - children: {ipInput}, - }, - ...(!(!this.state.needsPassword || this.state.hidePasswordInput) - ? [ - { - title: 'Wazuh password', - children: {passwordInput}, - }, - ] - : []), - { - title: 'Assign the agent to a group', - children: {groupInput}, - }, - { - title: 'Install and enroll the agent', - children: missingOSSelection.length ? ( - - ) : ( -
{guide}
- ), - }, - ...(this.state.selectedOS == 'rpm' || this.state.selectedOS == 'deb' - ? [ - { - title: 'Start the agent', - children: missingOSSelection.length ? ( - - ) : ( - - ), - }, - ] - : []), - - ...(!missingOSSelection.length && - this.state.selectedOS !== 'rpm' && - this.state.selectedOS !== 'deb' && - restartAgentCommand - ? [ - { - title: 'Start the agent', - children: ( - - - - {restartAgentCommand} - - - {(copy) => ( - - Copy command - - )} - - - - ), - }, - ] - : []), - ]; - return ( -
- - - - - - - - -

Deploy a new agent

-
-
- - {this.props.hasAgents && ( - this.props.addNewAgent(false)} - iconType="cross" - > - Close - - )} - {!this.props.hasAgents && ( - this.props.reload()} - iconType="refresh" - > - Refresh - - )} - + )} +
+ ); + + const tabs = [ + { + id: 'systemd', + name: 'Systemd', + content: ( + + + + + {this.systemSelector()} + + + {(copy) => ( + + Copy command + + )} + + {textAndLinkToCheckConnectionDocumentation} + + + ), + }, + { + id: 'sysV', + name: 'SysV Init', + content: ( + + + + + {this.systemSelector()} + + + {(copy) => ( + + Copy command + + )} + + {textAndLinkToCheckConnectionDocumentation} + + + ), + }, + ]; + + const steps = [ + { + title: 'Choose the Operating system', + children: ( + this.selectOS(os)} + /> + ), + }, + ...(this.state.selectedOS == 'rpm' + ? [ + { + title: 'Choose the version', + children: ( + this.setVersion(version)} + /> + ), + }, + ] + : []), + ...(this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos5' + ? [ + { + title: 'Choose the architecture', + children: ( + this.setArchitecture(architecture)} + /> + ), + }, + ] + : []), + ...(this.state.selectedOS == 'deb' || + (this.state.selectedOS == 'rpm' && this.state.selectedVersion == 'centos6') + ? [ + { + title: 'Choose the architecture', + children: ( + this.setArchitecture(architecture)} + /> + ), + }, + ] + : []), + { + title: 'Wazuh server address', + children: {ipInput}, + }, + ...(!(!this.state.needsPassword || this.state.hidePasswordInput) + ? [ + { + title: 'Wazuh password', + children: {passwordInput}, + }, + ] + : []), + { + title: 'Assign the agent to a group', + children: {groupInput}, + }, + { + title: 'Install and enroll the agent', + children: missingOSSelection.length ? ( + + ) : ( +
{guide}
+ ), + }, + ...(this.state.selectedOS == 'rpm' || this.state.selectedOS == 'deb' + ? [ + { + title: 'Start the agent', + children: missingOSSelection.length ? ( + + ) : ( + + ), + }, + ] + : []), + + ...(!missingOSSelection.length && + this.state.selectedOS !== 'rpm' && + this.state.selectedOS !== 'deb' && + restartAgentCommand + ? [ + { + title: 'Start the agent', + children: ( + + + + {restartAgentCommand} + + + {(copy) => ( + + Copy command + + )} + + - - {this.state.loading && ( - <> + ), + }, + ] + : []), + ]; + return ( +
+ + + + + + - + +

Deploy a new agent

+
- - - )} - {!this.state.loading && ( - - - - )} -
-
-
-
-
-
- ); + + {this.props.hasAgents && ( + this.props.addNewAgent(false)} + iconType="cross" + > + Close + + )} + {!this.props.hasAgents && ( + this.props.reload()} + iconType="refresh" + > + Refresh + + )} + + + + {this.state.loading && ( + <> + + + + + + )} + {!this.state.loading && ( + + + + )} + + + + + +
+ ); + } } -}) +);