From c525de67a326eb2ac41f0038657cfdd44800177a Mon Sep 17 00:00:00 2001 From: Adri Valle Date: Thu, 1 Aug 2019 10:45:47 +0200 Subject: [PATCH] Read cluster info from registry --- .../settings/components/api-table.js | 16 +++-- public/controllers/settings/settings.js | 60 +++++++++++++++---- server/controllers/wazuh-api.js | 42 +++++++++++-- server/lib/update-registry.js | 39 +++++++++++- server/routes/wazuh-api.js | 16 +++++ 5 files changed, 149 insertions(+), 24 deletions(-) diff --git a/public/controllers/settings/components/api-table.js b/public/controllers/settings/components/api-table.js index 84779fb13f..c57bca2de4 100644 --- a/public/controllers/settings/components/api-table.js +++ b/public/controllers/settings/components/api-table.js @@ -34,15 +34,20 @@ export class ApiTable extends Component { this.editionEnabled = false; } - checkApiConnection() { + async bindClusterInfo() { if (this.editionEnabled) return; - this.props.apiEntries.map(api => { - this.props.checkManager(api, false, true); + const result = await this.props.getApisInRegistry(); + const hosts = result.data || []; + hosts.map(h => { + const idx = this.props.getSelectedApiIndex(h); + delete h.id; + this.props.apiEntries[idx].cluster_info = h; }); + this.props.digest(); } shouldComponentUpdate() { - this.checkApiConnection(); + this.bindClusterInfo(); return true; } @@ -260,6 +265,9 @@ ApiTable.propTypes = { updateSettings: PropTypes.func, setDefault: PropTypes.func, checkManager: PropTypes.func, + getApisInRegistry: PropTypes.func, + getSelectedApiIndex: PropTypes.func, + digest: PropTypes.func, removeManager: PropTypes.func, switch: PropTypes.func }; diff --git a/public/controllers/settings/settings.js b/public/controllers/settings/settings.js index 10baa50077..674fef7971 100644 --- a/public/controllers/settings/settings.js +++ b/public/controllers/settings/settings.js @@ -114,6 +114,9 @@ export class SettingsController { setDefault: entry => this.setDefault(entry), checkManager: (entry, isIndex = false, silent = false) => this.checkManager(entry, isIndex, silent), removeManager: entry => this.removeManager(entry), + getApisInRegistry: () => this.getApisInRegistry(), + getSelectedApiIndex: item => this.getSelectedApiIndex(item), + digest: () => this.$scope.$applyAsync(), updateSettings: (entry, useItem = false) => this.updateSettings(entry, useItem), switch: () => this.switch() @@ -434,6 +437,7 @@ export class SettingsController { '/api/host', tmpData ); + this.appState.setExtensions(data.data.response._id, tmpData.extensions); const newEntry = { _id: ((data || {}).data).response || false, @@ -450,7 +454,9 @@ export class SettingsController { this.setDefault(newEntry); } this.$scope.$applyAsync(); - + // Store the cluster info in the registry + await this.saveApiInRegistry(newEntry); + const index = this.apiTableProps.apiEntries.length - 1; this.errorHandler.info('Wazuh API successfully added', 'Settings'); this.addManagerContainer = false; @@ -460,20 +466,20 @@ export class SettingsController { if (!this.appState.getCurrentAPI()) { // No cookie if ( - this.apiTableProps.apiEntries[this.apiTableProps.apiEntries.length - 1].cluster_info + this.apiTableProps.apiEntries[index].cluster_info .status === 'disabled' ) { this.appState.setCurrentAPI( JSON.stringify({ - name: this.apiTableProps.apiEntries[this.apiTableProps.apiEntries.length - 1].cluster_info.manager, - id: this.apiTableProps.apiEntries[this.apiTableProps.apiEntries.length - 1]._id + name: this.apiTableProps.apiEntries[index].cluster_info.manager, + id: this.apiTableProps.apiEntries[index]._id }) ); } else { this.appState.setCurrentAPI( JSON.stringify({ - name: this.apiTableProps.apiEntries[this.apiTableProps.apiEntries.length - 1].cluster_info.cluster, - id: this.apiTableProps.apiEntries[this.apiTableProps.apiEntries.length - 1]._id + name: this.apiTableProps.apiEntries[index].cluster_info.cluster, + id: this.apiTableProps.apiEntries[index]._id }) ); } @@ -560,7 +566,8 @@ export class SettingsController { const data = await this.testAPI.check(tmpData); tmpData.cluster_info = data.data; await this.genericReq.request('PUT', '/api/settings', tmpData); - this.apiTableProps.apiEntries[index].cluster_info = tmpData.cluster_info; + // Update the cluster info in the registry + await this.saveApiInRegistry(tmpData); this.wzMisc.setApiIsDown(false); this.apiIsDown = false; @@ -598,7 +605,8 @@ export class SettingsController { * @param {Object} item */ getSelectedApiIndex(item) { - return this.apiTableProps.apiEntries.map(item => (item._id).toString()).indexOf((item._id).toString()); + const id = item._id || item.id; + return this.apiTableProps.apiEntries.map(item => (item._id).toString()).indexOf((id).toString()); } // Check manager connectivity @@ -619,10 +627,6 @@ export class SettingsController { const data = await this.testAPI.check(tmpData); tmpData.cluster_info = data.data; - /*const tmpUrl = `/elastic/api-hostname/${this.apiTableProps.apiEntries[index]._id}`; - await this.genericReq.request('PUT', tmpUrl, { - cluster_info: tmpData.cluster_info - });*/ // Emit updateAPI event cause the cluster info could had been changed this.$scope.$emit('updateAPI', { cluster_info: tmpData.cluster_info }); this.apiTableProps.apiEntries[index].cluster_info = tmpData.cluster_info; @@ -819,4 +823,36 @@ export class SettingsController { this.errorHandler.handle(error); } } + + /** + * Get the hosts in the registry + */ + async getApisInRegistry() { + try { + return await this.genericReq.request( + 'GET', + '/apis/registry' + ); + } catch (error) { + return Promise.reject(error); + } + } + + /** + * Saves the cluster info of the API in the registry + * @param {Object} newEntry + */ + async saveApiInRegistry(newEntry){ + try { + const id = newEntry._id || newEntry.id; + const host = Object.assign({id: id}, newEntry.cluster_info); + await this.genericReq.request( + 'POST', + '/api/registry/add', + host + ) + } catch (error) { + return Promise.reject(error); + } + } } diff --git a/server/controllers/wazuh-api.js b/server/controllers/wazuh-api.js index b8aa68a033..a9435189ed 100644 --- a/server/controllers/wazuh-api.js +++ b/server/controllers/wazuh-api.js @@ -112,7 +112,7 @@ export class WazuhApiCtrl { } await this.wazuhRegistry.updateWazuhClusterInfo(apiId, api.cluster_info); - + } catch (error) { log('wazuh-api:checkStoredAPI', error.message || error); } @@ -285,12 +285,12 @@ export class WazuhApiCtrl { */ findApi(apis, apiId) { try { - log('wazuh-api:findApi', 'Finding API','debug'); + log('wazuh-api:findApi', 'Finding API', 'debug'); let data = apis.find((api) => { return Object.keys(api)[0] == apiId; }); data = Object.keys(data).length === 1 ? data[apiId] : data; - return data; + return data; } catch (error) { log('wazuh-api:findApi', error.message || error); throw error; @@ -860,7 +860,7 @@ export class WazuhApiCtrl { const devTools = !!(data || {}).devTools; try { const apis = (getConfiguration() || {})['wazuh.hosts'] || [] - const api = this.findApi(apis, id); + const api = this.findApi(apis, id); if (devTools) { delete data.devTools; } @@ -1260,7 +1260,7 @@ export class WazuhApiCtrl { throw new Error('Field api is required'); const apis = (getConfiguration() || {})['wazuh.hosts'] || [] - const config = this.findApi(apis, req.params.api); + const config = this.findApi(apis, req.params.api); const headers = ApiHelper.buildOptionsObject(config); const distinctUrl = `${config.url}:${config.port}/agents/stats/distinct`; @@ -1694,4 +1694,36 @@ export class WazuhApiCtrl { ); } } + + /** + * Get the hosts in the registry + */ + async getApisInRegistry(req, reply){ + try { + log('wazuh-api:getApisInRegistry', 'Getting APIs info fromt registry', 'debug'); + return await this.wazuhRegistry.getHosts(); + } catch (error) { + log('wazuh-api:getApisInRegistry', error.message || error); + return ErrorResponse('Cannot get the hosts in the wazuh-registry.json'); + } + } + + /** + * Returns the cluster information associated to an API id + * @param {Object} req + * @param {Object} reply + */ + async saveApiInRegistry(req, reply) { + try { + log('wazuh-api:saveApiInRegistry', 'Saving API info in registry', 'debug'); + if (!req || !req.payload || !req.payload.id) throw new Error('API id is missing'); + const info = req.payload; + const id = info.id; + delete info.id; + return await this.wazuhRegistry.updateWazuhClusterInfo(id, info); + } catch (error) { + log('wazuh-api:getClusterInfoByAPI', error.message || error); + return ErrorResponse('Missing parameters', 2015, 500, reply); + } + } } diff --git a/server/lib/update-registry.js b/server/lib/update-registry.js index c18f90238a..aa712c7db2 100644 --- a/server/lib/update-registry.js +++ b/server/lib/update-registry.js @@ -12,6 +12,7 @@ import fs from 'fs'; import path from 'path'; import { log } from '../logger'; +import { ErrorResponse } from '../controllers/error-response'; export class UpdateRegistry { constructor() { @@ -25,8 +26,8 @@ export class UpdateRegistry { */ async readContent(){ try { - const content = await fs.readFileSync(this.file, { encoding: 'utf-8' }); log('update-registry:readContent', 'Reading wazuh-registry.json content', 'debug'); + const content = await fs.readFileSync(this.file, { encoding: 'utf-8' }); return JSON.parse(content); } catch (error) { log('update-registry:readContent', error.message || error); @@ -34,19 +35,33 @@ export class UpdateRegistry { } } + /** + * Get the hosts and their cluster info stored in the registry + */ + async getHosts() { + try { + log('update-registry:getHosts', 'Getting hosts from registry', 'debug'); + const content = await this.readContent(); + return content.hosts; + } catch (error) { + log('update-registry:getHosts', error.message || error); + return Promise.reject(error); + } + } + /** * Writes the wazuh-registry.json * @param {Object} content */ async writeContent(content){ try { + log('update-registry:writeContent', 'Writting wazuh-registry.json content', 'debug'); if (this.busy) { throw new Error('Another process is updating the registry file'); } this.busy = true; await fs.writeFileSync(this.file, JSON.stringify(content)); this.busy = false; - log('update-registry:writeContent', 'Writting wazuh-registry.json content', 'debug'); } catch (error) { log('update-registry:writeContent', error.message || error); return Promise.reject(error) @@ -54,7 +69,7 @@ export class UpdateRegistry { } /** - * Uptades the cluster information associated with the current selected API + * Uptades the cluster information associated with an API id * @param {String} id * @param {Object} clusterInfo */ @@ -70,6 +85,7 @@ export class UpdateRegistry { } this.writeContent(content); log('update-registry:updateWazuhClusterInfo', `API ${id} was properly updated`, 'debug'); + return `API ${id} was successful updated.`; } catch (error) { log('update-registry:updateWazuhClusterInfo', error.message || error); return Promise.reject(error); @@ -149,4 +165,21 @@ export class UpdateRegistry { return Promise.reject(error); } } + + /** + * Returns the cluster information associated to an API id + * @param {String} id + */ + async getClusterInfoByAPI(id){ + try { + if (!id) throw new Error('API id is missing'); + const hosts = await this.getHosts(); + const info = hosts.filter(h => { + return h.id == id; + }); + } catch (error) { + log('update-registry:getClusterInfoByAPI', error.message || error); + return Promise.reject(error); + } + } } \ No newline at end of file diff --git a/server/routes/wazuh-api.js b/server/routes/wazuh-api.js index 04d699c56c..3defe4aca5 100644 --- a/server/routes/wazuh-api.js +++ b/server/routes/wazuh-api.js @@ -175,4 +175,20 @@ export function WazuhApiRoutes(server) { return ctrl.updateFullAPI(req, reply); } }); + + server.route({ + method: 'GET', + path: '/apis/registry', + handler(req, reply) { + return ctrl.getApisInRegistry(req, reply); + } + }); + + server.route({ + method: 'POST', + path: '/api/registry/add', + handler(req, reply) { + return ctrl.saveApiInRegistry(req, reply); + } + }); }