From 9e9e775ab9d263dd8e618cdac38c7e26e80b670a Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Mon, 6 May 2019 11:34:22 +0200 Subject: [PATCH 1/6] Check the Wazuh and App version on each transition --- .../appserver/static/js/run/run.js | 16 +++++-- .../js/services/api-manager/apiMgrService.js | 44 ++++++++++++++++--- .../currentDataService/currentDataService.js | 14 +++++- 3 files changed, 65 insertions(+), 9 deletions(-) diff --git a/SplunkAppForWazuh/appserver/static/js/run/run.js b/SplunkAppForWazuh/appserver/static/js/run/run.js index 2b3f718b2..4277afb92 100644 --- a/SplunkAppForWazuh/appserver/static/js/run/run.js +++ b/SplunkAppForWazuh/appserver/static/js/run/run.js @@ -1,4 +1,4 @@ -define(['./module'], function(module) { +define(['./module'], function (module) { 'use strict' module.run([ '$rootScope', @@ -6,7 +6,7 @@ define(['./module'], function(module) { '$transitions', '$navigationService', '$currentDataService', - function( + function ( $rootScope, $state, $transitions, @@ -27,7 +27,7 @@ define(['./module'], function(module) { ) $currentDataService.addFilter( `{"index":"${ - $currentDataService.getIndex().index + $currentDataService.getIndex().index }", "implicit":true}` ) // If change the primary state and do not receive an error the two below code lines clear the warning message @@ -54,6 +54,16 @@ define(['./module'], function(module) { // Check secondary states when Wazuh is not ready to prevent change the state $transitions.onBefore({}, async trans => { const to = trans.to().name + + try { + if (!to.startsWith('settings')) { + await $currentDataService.checkWazuhVersion() + } + } catch (error) { + $state.go('settings.api') + return false + } + if ( to !== 'overview' && to !== 'manager' && diff --git a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js index 32fed88b3..ba6161034 100644 --- a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js +++ b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js @@ -1,6 +1,6 @@ -define(['../module'], function(module) { +define(['../module'], function (module) { 'use strict' - module.service('$apiMgrService', function( + module.service('$apiMgrService', function ( $requestService, $apiIndexStorageService, $splunkStoreService @@ -222,9 +222,9 @@ define(['../module'], function(module) { const clusterEnabled = api.filterType === 'cluster.name' const checkConnectionEndpoint = `/manager/check_connection?ip=${ api.url - }&port=${ + }&port=${ api.portapi - }&user=${user}&pass=${pass}&cluster=${clusterEnabled}` + }&user=${user}&pass=${pass}&cluster=${clusterEnabled}` const result = await $requestService.httpReq( 'GET', checkConnectionEndpoint @@ -313,6 +313,39 @@ define(['../module'], function(module) { } } + + /** + * Checks if the Splunk Version are the same that the Wazuh version + */ + const checkWazuhVersion = async () => { + try { + const wazuhVersion = await $requestService.apiReq('/version') + const appVersion = await $requestService.httpReq( + 'GET', + '/manager/app_info' + ) + if ( + wazuhVersion.data && + wazuhVersion.data.data && + !wazuhVersion.data.error && + appVersion.data && + appVersion.data.version && + !appVersion.data.error + ) { + const wv = wazuhVersion.data.data + const av = appVersion.data.version + const wazuhSplit = wv.split('v')[1].split('.') + const appSplit = av.split('.') + + if (wazuhSplit[0] !== appSplit[0] || wazuhSplit[1] !== appSplit[1]) { + throw new Error(`Unexpected Wazuh version. App version: ${appSplit[0]}.${appSplit[1]}, Wazuh version: ${wazuhSplit[0]}.${wazuhSplit[1]}`) + } + } + } catch (error) { + return Promise.reject(error) + } + } + return { checkApiConnection: checkApiConnection, checkPollingState: checkPollingState, @@ -330,7 +363,8 @@ define(['../module'], function(module) { setIndex: setIndex, getApi: getApi, setApi: setApi, - addApi: addApi + addApi: addApi, + checkWazuhVersion: checkWazuhVersion } }) }) diff --git a/SplunkAppForWazuh/appserver/static/js/services/currentDataService/currentDataService.js b/SplunkAppForWazuh/appserver/static/js/services/currentDataService/currentDataService.js index 6aea99c93..abfa5e306 100644 --- a/SplunkAppForWazuh/appserver/static/js/services/currentDataService/currentDataService.js +++ b/SplunkAppForWazuh/appserver/static/js/services/currentDataService/currentDataService.js @@ -213,6 +213,17 @@ define(['../module'], function(module) { } } + /** + * Checks if the Splunk Version are the same that the Wazuh version + */ + const checkWazuhVersion = async () => { + try { + return await $apiMgrService.checkWazuhVersion() + } catch (error) { + return Promise.reject(error) + } + } + return { getPollintState: getPollintState, getBaseUrl: getBaseUrl, @@ -248,7 +259,8 @@ define(['../module'], function(module) { setExtensions: setExtensions, addApi: addApi, isAdmin: isAdmin, - getReportingStatus: getReportingStatus + getReportingStatus: getReportingStatus, + checkWazuhVersion: checkWazuhVersion } }) }) From 3da0a0adc08518c845be58f329134eec9530340c Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Mon, 6 May 2019 11:45:15 +0200 Subject: [PATCH 2/6] Show error toast when unexpected versions is found --- SplunkAppForWazuh/appserver/static/js/run/run.js | 5 ++++- .../static/js/services/api-manager/apiMgrService.js | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/SplunkAppForWazuh/appserver/static/js/run/run.js b/SplunkAppForWazuh/appserver/static/js/run/run.js index 4277afb92..3d2f8972e 100644 --- a/SplunkAppForWazuh/appserver/static/js/run/run.js +++ b/SplunkAppForWazuh/appserver/static/js/run/run.js @@ -6,12 +6,14 @@ define(['./module'], function (module) { '$transitions', '$navigationService', '$currentDataService', + '$notificationService', function ( $rootScope, $state, $transitions, $navigationService, - $currentDataService + $currentDataService, + $notificationService ) { //Go to last state or to a specified tab if "currentTab" param is specified in the url $navigationService.manageState() @@ -60,6 +62,7 @@ define(['./module'], function (module) { await $currentDataService.checkWazuhVersion() } } catch (error) { + $notificationService.showErrorToast(error || 'Unexpected Wazuh Version.') $state.go('settings.api') return false } diff --git a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js index ba6161034..1bbe371e3 100644 --- a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js +++ b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js @@ -338,7 +338,7 @@ define(['../module'], function (module) { const appSplit = av.split('.') if (wazuhSplit[0] !== appSplit[0] || wazuhSplit[1] !== appSplit[1]) { - throw new Error(`Unexpected Wazuh version. App version: ${appSplit[0]}.${appSplit[1]}, Wazuh version: ${wazuhSplit[0]}.${wazuhSplit[1]}`) + throw `Unexpected Wazuh version. App version: ${appSplit[0]}.${appSplit[1]}, Wazuh version: ${wazuhSplit[0]}.${wazuhSplit[1]}` } } } catch (error) { From e223a68d5c1f376a308ab19cdc61f63d3b3c8589 Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Mon, 6 May 2019 13:41:56 +0200 Subject: [PATCH 3/6] Check Wazuh version in the backend --- .../appserver/controllers/manager.py | 52 +++++++++++++++++-- .../settings/api/settingsApiCtrl.js | 8 +-- .../js/services/api-manager/apiMgrService.js | 6 +-- 3 files changed, 56 insertions(+), 10 deletions(-) diff --git a/SplunkAppForWazuh/appserver/controllers/manager.py b/SplunkAppForWazuh/appserver/controllers/manager.py index 9ce52b870..778cf3534 100644 --- a/SplunkAppForWazuh/appserver/controllers/manager.py +++ b/SplunkAppForWazuh/appserver/controllers/manager.py @@ -316,6 +316,11 @@ def check_connection(self, **kwargs): request_cluster_name = self.session.get( url + '/cluster/node', auth=auth, timeout=20, verify=verify).json() output = {} + try: + self.check_wazuh_version(kwargs) + except Exception as e: + error = {"status": 400, "error": str(e)} + return jsonbak.dumps(error) daemons_ready = self.check_daemons(url, auth, verify, opt_cluster) # Pass the cluster status instead of always False if not daemons_ready: @@ -328,12 +333,52 @@ def check_connection(self, **kwargs): except Exception as e: if not daemons_ready: self.logger.error("Cannot connect to API; Wazuh not ready yet.") - return jsonbak.dumps({"status": "200", "error": 3099, "message": "Wazuh not ready yet."}) + return jsonbak.dumps({"status": 200, "error": 3099, "message": "Wazuh not ready yet."}) else: self.logger.error("Cannot connect to API : %s" % (e)) - return jsonbak.dumps({"status": "400", "error": "Cannot connect to the API"}) + return jsonbak.dumps({"status": 400, "error": "Cannot connect to the API"}) return result + def check_wazuh_version(self, kwargs): + """Check Wazuh version + + Parameters + ---------- + kwargs : dict + The request's parameters + """ + try: + opt_username = kwargs["user"] + opt_password = kwargs["pass"] + opt_base_url = kwargs["ip"] + opt_base_port = kwargs["port"] + url = opt_base_url + ":" + opt_base_port + auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) + verify = False + + wazuh_version = self.session.get( + url + '/version', auth=auth, timeout=20, verify=verify).json() + wazuh_version = wazuh_version['data'] + wazuh_version = wazuh_version.split('v')[1] + + app_version = cli.getConfStanza( + 'package', + 'app') + app_version = app_version['version'] + + v_split = wazuh_version.split('.') + a_split = app_version.split('.') + + wazuh_version = str(v_split[0]+"."+v_split[1]) + app_version = str(a_split[0]+"."+a_split[1]) + if wazuh_version != app_version: + raise Exception("Unexpected Wazuh version. App version: %s, Wazuh version: %s" % (app_version, wazuh_version)) + except Exception as e: + self.logger.error("Error when checking Wazuh version: %s" % (e)) + raise e + + + def check_daemons(self, url, auth, verify, check_cluster): """ Request to check the status of this daemons: execd, modulesd, wazuhdb and clusterd @@ -367,4 +412,5 @@ def check_daemons(self, url, auth, verify, check_cluster): return wazuh_ready except Exception as e: self.logger.error("Error checking daemons: %s" % (e)) - raise e \ No newline at end of file + raise e + return \ No newline at end of file diff --git a/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js b/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js index fd5e325db..9ed52c459 100644 --- a/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js +++ b/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js @@ -121,7 +121,7 @@ define(['../../module'], function(controllers) { this.notification.showSuccessToast('Connection established') if (!this.scope.$$phase) this.scope.$digest() } catch (err) { - this.notification.showErrorToast('Unreachable API') + this.notification.showErrorToast(err || 'Unreachable API') } } @@ -201,7 +201,7 @@ define(['../../module'], function(controllers) { this.scope.edit = false this.notification.showSuccessToast('Updated API') } catch (err) { - this.notification.showErrorToast('Cannot update API') + this.notification.showErrorToast(err || 'Cannot update API') } this.savingApi = false } @@ -221,7 +221,7 @@ define(['../../module'], function(controllers) { this.scope.$emit('updatedAPI', () => {}) if (!this.scope.$$phase) this.scope.$digest() } catch (err) { - this.notification.showErrorToast('Could not select manager') + this.notification.showErrorToast(err || 'Could not select manager') } } @@ -279,7 +279,7 @@ define(['../../module'], function(controllers) { if (!this.scope.$$phase) this.scope.$digest() this.notification.showSuccessToast('New API was added') } catch (err) { - this.notification.showErrorToast(err.message) + this.notification.showErrorToast(err.message || err || 'Cannot save the API.') } this.savingApi = false } diff --git a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js index 1bbe371e3..4ad0aa32c 100644 --- a/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js +++ b/SplunkAppForWazuh/appserver/static/js/services/api-manager/apiMgrService.js @@ -231,15 +231,15 @@ define(['../module'], function (module) { ) if (result.data.status === 400 || result.data.error) { if (result.data.error === 3099) { - throw new Error('ERROR3099 - Wazuh not ready yet.') + throw 'ERROR3099 - Wazuh not ready yet.' } else { - throw new Error('Unreachable API.') + throw result.data.error || 'Unreachable API.' } } return result } // Otherwise throw a new error - throw new Error('Missing API fields.') + throw 'Missing API fields.' } catch (err) { return Promise.reject(err) } From 2f62f3f4e4abf69c5e73a591eb551017cf08cf94 Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Thu, 2 May 2019 12:11:09 +0200 Subject: [PATCH 4/6] Resolving cherry-pick conflicts --- .../appserver/controllers/manager.py | 21 +++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/SplunkAppForWazuh/appserver/controllers/manager.py b/SplunkAppForWazuh/appserver/controllers/manager.py index 778cf3534..4e0a77095 100644 --- a/SplunkAppForWazuh/appserver/controllers/manager.py +++ b/SplunkAppForWazuh/appserver/controllers/manager.py @@ -309,12 +309,21 @@ def check_connection(self, **kwargs): url = opt_base_url + ":" + opt_base_port auth = requestsbak.auth.HTTPBasicAuth(opt_username, opt_password) verify = False - request_manager = self.session.get( - url + '/agents/000?select=name', auth=auth, timeout=20, verify=verify).json() - request_cluster = self.session.get( - url + '/cluster/status', auth=auth, timeout=20, verify=verify).json() - request_cluster_name = self.session.get( - url + '/cluster/node', auth=auth, timeout=20, verify=verify).json() + try: + # Checks in the first request if the credentials are ok + request_manager = self.session.get( + url + '/agents/000?select=name', auth=auth, timeout=20, verify=verify) + if request_manager.status_code == 401: + self.logger.error("Cannot connect to API; Invalid credentials.") + return jsonbak.dumps({"status": "400", "error": "Invalid credentials, please check the username and password."}) + request_manager = request_manager.json() + request_cluster = self.session.get( + url + '/cluster/status', auth=auth, timeout=20, verify=verify).json() + request_cluster_name = self.session.get( + url + '/cluster/node', auth=auth, timeout=20, verify=verify).json() + except ConnectionError as e: + self.logger.error("Cannot connect to API : %s" % (e)) + return jsonbak.dumps({"status": "400", "error": "Unreachable API, please check the URL and port."}) output = {} try: self.check_wazuh_version(kwargs) From 790ef62f509382c36cf4bd45beb02c557102779d Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Thu, 2 May 2019 11:51:26 +0200 Subject: [PATCH 5/6] Resolving cherry-pick conflicts --- SplunkAppForWazuh/appserver/controllers/manager.py | 1 + 1 file changed, 1 insertion(+) diff --git a/SplunkAppForWazuh/appserver/controllers/manager.py b/SplunkAppForWazuh/appserver/controllers/manager.py index 4e0a77095..82dfdcff7 100644 --- a/SplunkAppForWazuh/appserver/controllers/manager.py +++ b/SplunkAppForWazuh/appserver/controllers/manager.py @@ -22,6 +22,7 @@ from splunk.appserver.mrsparkle.lib.decorators import expose_page from db import database from log import log +from requestsbak.exceptions import ConnectionError def getSelfConfStanza(file, stanza): From bd92d42d141bc447cdbb4aa02a11788d24c2f4cb Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Mon, 6 May 2019 14:03:15 +0200 Subject: [PATCH 6/6] Show as persistent error when unexpected Wazuh version is found --- .../static/js/controllers/settings/api/settingsApiCtrl.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js b/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js index 9ed52c459..7a5fb491d 100644 --- a/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js +++ b/SplunkAppForWazuh/appserver/static/js/controllers/settings/api/settingsApiCtrl.js @@ -279,7 +279,11 @@ define(['../../module'], function(controllers) { if (!this.scope.$$phase) this.scope.$digest() this.notification.showSuccessToast('New API was added') } catch (err) { - this.notification.showErrorToast(err.message || err || 'Cannot save the API.') + if (err.startsWith('Unexpected Wazuh version')) { + this.scope.validatingError.push(err) + } else { + this.notification.showErrorToast(err.message || err || 'Cannot save the API.') + } } this.savingApi = false }