Code quality(eslint, mocha, tslint)

This commit is contained in:
Jesús Ángel 2018-09-03 11:46:55 +02:00
parent 513b134c0a
commit 9dd02ea153
52 changed files with 619 additions and 687 deletions

View File

@ -11,17 +11,19 @@
"jsx": true
}
},
"globals": {
"XPACK_RBAC_ENABLED": true
},
"parser": "babel-eslint",
"rules": {
"node/exports-style": ["error", "module.exports"],
"semi": 0,
"no-console": 0,
"no-process-exit": 0,
"no-console": "warn",
"semi": "off",
"no-process-exit": "error",
"no-extra-boolean-cast": "off",
"node/no-unpublished-require": 0,
"node/no-unsupported-features": 0,
"node/no-unsupported-features/es-syntax": 0,
"no-extra-boolean-cast": 0,
"no-cond-assign": 0
"node/no-unsupported-features/es-syntax": 0
},
"plugins": ["node", "async-await"],
"extends": ["eslint:recommended", "plugin:node/recommended"]

2
.tslint.yml Normal file
View File

@ -0,0 +1,2 @@
extends:
- tslint:recommended

View File

@ -11,7 +11,7 @@
*/
// Imports the init module
import init from './init';
import { initApp } from './init';
export default kibana => new kibana.Plugin({
id: 'wazuh',
@ -26,6 +26,5 @@ export default kibana => new kibana.Plugin({
main: 'plugins/wazuh/app'
}
},
init: (server,options) => init(server,options)
});
init(server,options) { return initApp(server,options) }
});

28
init.js
View File

@ -11,18 +11,18 @@
*/
// Imports all server modules
import initialize from './server/initialize';
import wazuhElastic from './server/routes/wazuh-elastic';
import wazuhApiElastic from './server/routes/wazuh-api-elastic';
import monitoring from './server/monitoring';
import wazuhApi from './server/routes/wazuh-api';
import wazuhReporting from './server/routes/wazuh-reporting';
import { Initialize } from './server/initialize';
import { WazuhElasticRouter } from './server/routes/wazuh-elastic';
import { WazuhApiElasticRoutes } from './server/routes/wazuh-api-elastic';
import { Monitoring } from './server/monitoring';
import { WazuhApiRoutes } from './server/routes/wazuh-api';
import { WazuhReportingRoutes } from './server/routes/wazuh-reporting';
export default (server, options) => {
initialize(server, options);
wazuhElastic(server, options);
wazuhApiElastic(server, options);
monitoring(server, false);
wazuhApi(server, options);
wazuhReporting(server, options);
};
export function initApp (server) {
Initialize(server);
WazuhElasticRouter(server);
WazuhApiElasticRoutes(server);
Monitoring(server, false);
WazuhApiRoutes(server);
WazuhReportingRoutes(server);
}

View File

@ -26,9 +26,11 @@
},
"homepage": "https://www.wazuh.com/",
"scripts": {
"tslint": "tslint -c .tslint.yml server/**/*.ts server/**/*.tsx public/**/*.ts public/**/*.tsx",
"lint": "eslint server/** server/*.js *.js public/**/*.js public/*.js util/*.js -c .eslintrc.json --color",
"prebuild": "tsc; find . -name \"*.ts*\" -type f -not -path \"./node_modules/*\" -delete",
"build": "plugin-helpers build"
"build": "plugin-helpers build",
"test": "_mocha test/**/*"
},
"dependencies": {
"angular-animate": "1.6.5",
@ -53,6 +55,8 @@
"eslint-plugin-async-await": "^0.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"mocha": "^5.2.0",
"chai": "^3.5.0",
"tslint": "^5.11.0",
"typescript": "^3.0.1",
"typescript-eslint-parser": "^18.0.0"

View File

@ -80,12 +80,12 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
genericReq.request('GET', '/api/wazuh-api/agents-unique/' + api, {}),
genericReq.request('GET', `/api/wazuh-elastic/top/${firstUrlParam}/${secondUrlParam}/agent.name/${pattern}`)
]);
const unique = data[0].data.result;
const [agentsUnique,agentsTop] = data;
const unique = agentsUnique.data.result;
$scope.groups = unique.groups;
$scope.nodes = unique.nodes.map(item => { return {id: item} });
$scope.versions = unique.versions.map(item => { return {id: item} });
$scope.nodes = unique.nodes.map(item => ({id: item}));
$scope.versions = unique.versions.map(item => ({id: item}));
$scope.osPlatforms = unique.osPlatforms;
$scope.lastAgent = unique.lastAgent;
$scope.agentsCountActive = unique.summary.agentsCountActive;
@ -94,11 +94,11 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
$scope.agentsCountTotal = unique.summary.agentsCountTotal;
$scope.agentsCoverity = unique.summary.agentsCoverity;
if (data[1].data.data === '') {
if (agentsTop.data.data === '') {
$scope.mostActiveAgent.name = appState.getClusterInfo().manager;
$scope.mostActiveAgent.id = '000';
} else {
$scope.mostActiveAgent.name = data[1].data.data;
$scope.mostActiveAgent.name = agentsTop.data.data;
const info = await genericReq.request('GET', `/api/wazuh-elastic/top/${firstUrlParam}/${secondUrlParam}/agent.id/${pattern}`);
if (info.data.data === '' && $scope.mostActiveAgent.name !== '') {
$scope.mostActiveAgent.id = '000';

View File

@ -9,13 +9,13 @@
*
* Find more information about this on the LICENSE file.
*/
import beautifier from '../../utils/json-beautifier';
import { uiModules } from 'ui/modules';
import FilterHandler from '../../utils/filter-handler';
import generateMetric from '../../utils/generate-metric';
import TabNames from '../../utils/tab-names';
import * as FileSaver from '../../services/file-saver';
import TabDescription from '../../../server/reporting/tab-description';
import beautifier from '../../utils/json-beautifier';
import { uiModules } from 'ui/modules';
import { FilterHandler } from '../../utils/filter-handler';
import generateMetric from '../../utils/generate-metric';
import TabNames from '../../utils/tab-names';
import * as FileSaver from '../../services/file-saver';
import TabDescription from '../../../server/reporting/tab-description';
import {
metricsAudit,

View File

@ -95,7 +95,7 @@ class Logs {
try{
const data = await this.apiReq.request('GET', '/manager/logs/summary', {});
const daemons = data.data.data;
this.$scope.daemons = Object.keys(daemons).map(item => { return { title: item } })
this.$scope.daemons = Object.keys(daemons).map(item => ({ title: item }))
if(!this.$scope.$$phase) this.$scope.$digest();
return;
} catch (error) {

View File

@ -9,8 +9,8 @@
*
* Find more information about this on the LICENSE file.
*/
import FilterHandler from '../../utils/filter-handler'
import { uiModules } from 'ui/modules'
import { FilterHandler } from '../../utils/filter-handler'
import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);

View File

@ -50,23 +50,27 @@ class StatusController {
this.apiReq.request('GET', '/rules', { offset: 0, limit: 1 }),
this.apiReq.request('GET', '/decoders', { offset: 0, limit: 1 })
])
const parsedData = data.map(item => item.data.data);
const [stats, daemons, managerInfo, totalRules, totalDecoders] = parsedData;
// Once Wazuh core fixes agent 000 issues, this should be adjusted
const active = data[0].data.data.Active - 1;
const total = data[0].data.data.Total - 1;
const active = stats.Active - 1;
const total = stats.Total - 1;
this.$scope.agentsCountActive = active;
this.$scope.agentsCountDisconnected = data[0].data.data.Disconnected;
this.$scope.agentsCountNeverConnected = data[0].data.data['Never connected'];
this.$scope.agentsCountDisconnected = stats.Disconnected;
this.$scope.agentsCountNeverConnected = stats['Never connected'];
this.$scope.agentsCountTotal = total;
this.$scope.agentsCoverity = (active / total) * 100;
this.$scope.daemons = data[1].data.data;
this.$scope.managerInfo = data[2].data.data;
this.$scope.totalRules = data[3].data.data.totalItems;
this.$scope.totalDecoders = data[4].data.data.totalItems;
this.$scope.daemons = daemons;
this.$scope.managerInfo = managerInfo;
this.$scope.totalRules = totalRules.totalItems;
this.$scope.totalDecoders = totalDecoders.totalItems;
const lastAgent = await this.apiReq.request('GET', '/agents', { limit: 1, sort: '-dateAdd' });
const agentInfo = await this.apiReq.request('GET', `/agents/${lastAgent.data.data.items[0].id}`, {});
const lastAgentRaw = await this.apiReq.request('GET', '/agents', { limit: 1, sort: '-dateAdd' });
const [lastAgent] = lastAgentRaw.data.data.items;
const agentInfo = await this.apiReq.request('GET', `/agents/${lastAgent.id}`, {});
this.$scope.agentInfo = agentInfo.data.data;
this.$scope.load = false;

View File

@ -9,14 +9,23 @@
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import FilterHandler from '../../utils/filter-handler'
import generateMetric from '../../utils/generate-metric'
import TabNames from '../../utils/tab-names'
import { metricsGeneral, metricsFim, metricsAudit, metricsVulnerability, metricsScap, metricsCiscat, metricsVirustotal, metricsAws } from '../../utils/overview-metrics'
import { uiModules } from 'ui/modules';
import { FilterHandler } from '../../utils/filter-handler';
import generateMetric from '../../utils/generate-metric';
import TabNames from '../../utils/tab-names';
import TabDescription from '../../../server/reporting/tab-description';
import {
metricsGeneral,
metricsFim,
metricsAudit,
metricsVulnerability,
metricsScap,
metricsCiscat,
metricsVirustotal,
metricsAws
} from '../../utils/overview-metrics'
const app = uiModules.get('app/wazuh', []);
app.controller('overviewController',

View File

@ -17,7 +17,7 @@ app.directive('wzDynamic', function($compile) {
return {
restrict: 'A',
replace: true,
link: function(scope, ele, attrs) {
link(scope, ele, attrs) {
scope.$watch(attrs.wzDynamic, function(html) {
ele.html(html);
$compile(ele.contents())(scope);

View File

@ -29,7 +29,7 @@ app.directive('wzTable', function() {
rowSizes: '=rowSizes',
extraLimit: '=extraLimit'
},
controller: function($scope, apiReq, $timeout, shareAgent, $location, errorHandler, wzTableFilter, $window) {
controller($scope, apiReq, $timeout, shareAgent, $location, errorHandler, wzTableFilter, $window) {
/**
* Calculate number of table rows depending on the screen height
*/
@ -322,13 +322,13 @@ app.directive('wzTable', function() {
checkIfArray(item[key.value || key]) || '---';
};
},
template: template
template
}
})
.service('wzTableFilter',() => {
const filters = [];
return {
set: array => { if(Array.isArray(array)) { filters.length = 0; filters.push(...array); } },
get: () => filters
set (array) { if(Array.isArray(array)) { filters.length = 0; filters.push(...array); } },
get () { return filters }
};
});

View File

@ -69,14 +69,13 @@ import { BasicResponseHandlerProvider } from 'ui/vis/response_handlers/basic';
import { DocTitleProvider } from 'ui/doc_title';
import PluginsKibanaDiscoverHitSortFnProvider from 'plugins/kibana/discover/_hit_sort_fn';
import { FilterBarQueryFilterProvider } from 'ui/filter_bar/query_filter';
import { intervalOptions } from 'ui/agg_types/buckets/_interval_options';
import { stateMonitorFactory } from 'ui/state_management/state_monitor_factory';
import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery';
import { FilterManagerProvider } from 'ui/filter_manager';
import { visualizationLoader } from 'ui/visualize/loader/visualization_loader';
import { getDocLink } from 'ui/documentation_links';
import 'ui/courier/search_strategy/default_search_strategy'
import 'ui/courier/search_strategy/default_search_strategy';
const app = uiModules.get('apps/discover', [
'kibana/notify',
@ -413,7 +412,7 @@ $scope.toggleRefresh = () => {
////////////////////////////////////////////////////////////////////////////
$state.save();
}).catch(console.error);
}).catch(console.error); // eslint-disable-line
});
// update data source when hitting forward/back and the query changes
@ -689,7 +688,7 @@ $scope.toggleRefresh = () => {
const fields = _.keys(indexPattern.flattenHit(hit));
let n = fields.length;
let field;
while (field = fields[--n]) {
while (field = fields[--n]) { // eslint-disable-line
if (counts[field]) counts[field] += 1;
else counts[field] = 1;
}
@ -921,7 +920,7 @@ $scope.toggleRefresh = () => {
queryFilter.addFilters(wzCurrentFilters)
.then(() => { })
.catch(error => console.log(error.message || error));
.catch(error => console.log(error.message || error)); // eslint-disable-line
}
};

View File

@ -9,20 +9,21 @@
*
* Find more information about this on the LICENSE file.
*/
import $ from 'jquery';
import { uiModules } from 'ui/modules';
import $ from 'jquery';
import { uiModules } from 'ui/modules';
import { getVisualizeLoader } from './loader';
import { timefilter } from 'ui/timefilter'
import { timefilter } from 'ui/timefilter';
const app = uiModules.get('apps/webinar_app', []);
app.directive('kbnVis', [function () {
app.directive('kbnVis', function () {
return {
restrict: 'E',
scope: {
visID: '=visId',
specificTimeRange: '=specificTimeRange'
},
controller: function VisController($scope, $rootScope, wzsavedVisualizations, errorHandler, rawVisualizations, loadedVisualizations, tabVisualizations, discoverPendingUpdates, visHandlers) {
controller($scope, $rootScope, wzsavedVisualizations, errorHandler, rawVisualizations, loadedVisualizations, tabVisualizations, discoverPendingUpdates, visHandlers) {
let implicitFilter = '';
let rawFilters = [];
@ -132,7 +133,7 @@ app.directive('kbnVis', [function () {
$rootScope.rendered = thereIsData;
if(!thereIsData) $rootScope.resultState = 'none';
else $rootScope.resultState = 'ready';
}
}
// Forcing a digest cycle
if(!$rootScope.$$phase) $rootScope.$digest();
}
@ -143,4 +144,4 @@ app.directive('kbnVis', [function () {
let loader = null;
}
};
}]);
});

View File

@ -2,7 +2,7 @@ import _ from 'lodash'
import { Scanner } from 'ui/utils/scanner';
import { StringUtils } from 'ui/utils/string_utils';
import { SavedObjectsClient } from 'ui/saved_objects';
import { SavedObjectProvider } from './saved-objects';
export class SavedObjectLoader {
constructor(SavedObjectClass, kbnIndex, kbnUrl, $http, chrome ) {
this.type = SavedObjectClass.type;
@ -52,7 +52,7 @@ export class SavedObjectLoader {
// just assign the defaults and be done
_.assign(instance, instance.defaults);
return instance.hydrateIndexPattern().then(() => {
return afterESResp.call(instance);
return afterESResp.call(instance); // eslint-disable-line
});
}
return this.processFunc()

View File

@ -1,399 +0,0 @@
/**
* @name SavedObject
*
* NOTE: SavedObject seems to track a reference to an object in ES,
* and surface methods for CRUD functionality (save and delete). This seems
* similar to how Backbone Models work.
*
* This class seems to interface with ES primarily through the es Angular
* service and the saved object api.
*/
import angular from 'angular';
import _ from 'lodash';
import { SavedObjectNotFound } from 'ui/errors';
import MappingSetupProvider from 'ui/utils/mapping_setup';
import { SearchSourceProvider } from 'ui/courier';
import { SavedObjectsClientProvider, findObjectByTitle } from 'ui/saved_objects';
import { migrateLegacyQuery } from 'ui/utils/migrateLegacyQuery.js';
import { recentlyAccessed } from 'ui/persisted_log';
/**
* An error message to be used when the user rejects a confirm overwrite.
* @type {string}
*/
const OVERWRITE_REJECTED = 'Overwrite confirmation was rejected';
/**
* An error message to be used when the user rejects a confirm save with duplicate title.
* @type {string}
*/
const SAVE_DUPLICATE_REJECTED = 'Save with duplicate title confirmation was rejected';
/**
* @param error {Error} the error
* @return {boolean}
*/
function isErrorNonFatal(error) {
if (!error) return false;
return error.message === OVERWRITE_REJECTED || error.message === SAVE_DUPLICATE_REJECTED;
}
export function SavedObjectProvider(Promise, Private, Notifier, confirmModalPromise, indexPatterns) {
const savedObjectsClient = Private(SavedObjectsClientProvider);
const SearchSource = Private(SearchSourceProvider);
const mappingSetup = Private(MappingSetupProvider);
function SavedObject(config) {
if (!_.isObject(config)) config = {};
/************
* Initialize config vars
************/
// type name for this object, used as the ES-type
const esType = config.type;
this.getDisplayName = function () {
return esType;
};
// NOTE: this.type (not set in this file, but somewhere else) is the sub type, e.g. 'area' or
// 'data table', while esType is the more generic type - e.g. 'visualization' or 'saved search'.
this.getEsType = function () {
return esType;
};
/**
* Flips to true during a save operation, and back to false once the save operation
* completes.
* @type {boolean}
*/
this.isSaving = false;
this.defaults = config.defaults || {};
// mapping definition for the fields that this object will expose
const mapping = mappingSetup.expandShorthand(config.mapping);
const afterESResp = config.afterESResp || _.noop;
const customInit = config.init || _.noop;
// optional search source which this object configures
this.searchSource = config.searchSource ? new SearchSource() : undefined;
// the id of the document
this.id = config.id || void 0;
// Whether to create a copy when the object is saved. This should eventually go away
// in favor of a better rename/save flow.
this.copyOnSave = false;
const parseSearchSource = (searchSourceJson) => {
if (!this.searchSource) return;
// if we have a searchSource, set its values based on the searchSourceJson field
let searchSourceValues;
try {
searchSourceValues = JSON.parse(searchSourceJson);
} catch (e) {
searchSourceValues = {};
}
const searchSourceFields = this.searchSource.getFields();
const fnProps = _.transform(searchSourceFields, function (dynamic, val, name) {
if (_.isFunction(val)) dynamic[name] = val;
}, {});
this.searchSource.setFields(_.defaults(searchSourceValues, fnProps));
if (!_.isUndefined(this.searchSource.getOwnField('query'))) {
this.searchSource.setField('query', migrateLegacyQuery(this.searchSource.getOwnField('query')));
}
};
/**
* After creation or fetching from ES, ensure that the searchSources index indexPattern
* is an bonafide IndexPattern object.
*
* @return {Promise<IndexPattern | null>}
*/
this.hydrateIndexPattern = (id) => {
if (!this.searchSource) {
return Promise.resolve(null);
}
if (config.clearSavedIndexPattern) {
this.searchSource.setField('index', null);
return Promise.resolve(null);
}
let index = id || config.indexPattern || this.searchSource.getOwnField('index');
if (!index) {
return Promise.resolve(null);
}
// If index is not an IndexPattern object at this point, then it's a string id of an index.
if (!(index instanceof indexPatterns.IndexPattern)) {
index = indexPatterns.get(index);
}
// At this point index will either be an IndexPattern, if cached, or a promise that
// will return an IndexPattern, if not cached.
return Promise.resolve(index).then(indexPattern => {
this.searchSource.setField('index', indexPattern);
});
};
/**
* Asynchronously initialize this object - will only run
* once even if called multiple times.
*
* @return {Promise}
* @resolved {SavedObject}
*/
this.init = _.once(() => {
// ensure that the esType is defined
if (!esType) throw new Error('You must define a type name to use SavedObject objects.');
return Promise.resolve()
.then(() => {
// If there is not id, then there is no document to fetch from elasticsearch
if (!this.id) {
// just assign the defaults and be done
_.assign(this, this.defaults);
return this.hydrateIndexPattern().then(() => {
return afterESResp.call(this);
});
}
// fetch the object from ES
return savedObjectsClient.get(esType, this.id)
.then(resp => {
// temporary compatability for savedObjectsClient
return {
_id: resp.id,
_type: resp.type,
_source: _.cloneDeep(resp.attributes),
found: resp._version ? true : false
};
})
.then(this.applyESResp)
.catch(this.applyEsResp);
})
.then(() => customInit.call(this))
.then(() => this);
});
this.applyESResp = (resp) => {
this._source = _.cloneDeep(resp._source);
if (resp.found != null && !resp.found) {
throw new SavedObjectNotFound(esType, this.id);
}
const meta = resp._source.kibanaSavedObjectMeta || {};
delete resp._source.kibanaSavedObjectMeta;
if (!config.indexPattern && this._source.indexPattern) {
config.indexPattern = this._source.indexPattern;
delete this._source.indexPattern;
}
// assign the defaults to the response
_.defaults(this._source, this.defaults);
// transform the source using _deserializers
_.forOwn(mapping, (fieldMapping, fieldName) => {
if (fieldMapping._deserialize) {
this._source[fieldName] = fieldMapping._deserialize(this._source[fieldName], resp, fieldName, fieldMapping);
}
});
// Give obj all of the values in _source.fields
_.assign(this, this._source);
this.lastSavedTitle = this.title;
return Promise.try(() => {
parseSearchSource(meta.searchSourceJSON);
return this.hydrateIndexPattern();
}).then(() => {
return Promise.cast(afterESResp.call(this, resp));
});
};
/**
* Serialize this object
*
* @return {Object}
*/
this.serialize = () => {
const body = {};
_.forOwn(mapping, (fieldMapping, fieldName) => {
if (this[fieldName] != null) {
body[fieldName] = (fieldMapping._serialize)
? fieldMapping._serialize(this[fieldName])
: this[fieldName];
}
});
if (this.searchSource) {
const searchSourceFields = _.omit(this.searchSource.getFields(), ['sort', 'size']);
body.kibanaSavedObjectMeta = {
searchSourceJSON: angular.toJson(searchSourceFields)
};
}
return body;
};
/**
* Returns true if the object's original title has been changed. New objects return false.
* @return {boolean}
*/
this.isTitleChanged = () => {
return this._source && this._source.title !== this.title;
};
/**
* Attempts to create the current object using the serialized source. If an object already
* exists, a warning message requests an overwrite confirmation.
* @param source - serialized version of this object (return value from this.serialize())
* What will be indexed into elasticsearch.
* @returns {Promise} - A promise that is resolved with the objects id if the object is
* successfully indexed. If the overwrite confirmation was rejected, an error is thrown with
* a confirmRejected = true parameter so that case can be handled differently than
* a create or index error.
* @resolved {SavedObject}
*/
const createSource = (source) => {
return savedObjectsClient.create(esType, source, { id: this.id })
.catch(err => {
// record exists, confirm overwriting
if (_.get(err, 'res.status') === 409) {
const confirmMessage = `Are you sure you want to overwrite ${this.title}?`;
return confirmModalPromise(confirmMessage, { confirmButtonText: `Overwrite ${this.getDisplayName()}` })
.then(() => savedObjectsClient.create(esType, source, { id: this.id, overwrite: true }))
.catch(() => Promise.reject(new Error(OVERWRITE_REJECTED)));
}
return Promise.reject(err);
});
};
const displayDuplicateTitleConfirmModal = () => {
const confirmMessage =
`A ${this.getDisplayName()} with the title '${this.title}' already exists. Would you like to save anyway?`;
return confirmModalPromise(confirmMessage, { confirmButtonText: `Save ${this.getDisplayName()}` })
.catch(() => Promise.reject(new Error(SAVE_DUPLICATE_REJECTED)));
};
const checkForDuplicateTitle = (isTitleDuplicateConfirmed, onTitleDuplicate) => {
// Don't check for duplicates if user has already confirmed save with duplicate title
if (isTitleDuplicateConfirmed) {
return Promise.resolve();
}
// Don't check if the user isn't updating the title, otherwise that would become very annoying to have
// to confirm the save every time, except when copyOnSave is true, then we do want to check.
if (this.title === this.lastSavedTitle && !this.copyOnSave) {
return Promise.resolve();
}
return findObjectByTitle(savedObjectsClient, this.getEsType(), this.title)
.then(duplicate => {
if (!duplicate) return true;
if (duplicate.id === this.id) return true;
if (onTitleDuplicate) {
onTitleDuplicate();
return Promise.reject(new Error(SAVE_DUPLICATE_REJECTED));
}
// TODO: make onTitleDuplicate a required prop and remove UI components from this class
// Need to leave here until all users pass onTitleDuplicate.
return displayDuplicateTitleConfirmModal();
});
};
/**
* Saves this object.
*
* @param {object} [options={}]
* @property {boolean} [options.confirmOverwrite=false] - If true, attempts to create the source so it
* can confirm an overwrite if a document with the id already exists.
* @property {boolean} [options.isTitleDuplicateConfirmed=false] - If true, save allowed with duplicate title
* @property {func} [options.onTitleDuplicate] - function called if duplicate title exists.
* When not provided, confirm modal will be displayed asking user to confirm or cancel save.
* @return {Promise}
* @resolved {String} - The id of the doc
*/
this.save = ({ confirmOverwrite = false, isTitleDuplicateConfirmed = false, onTitleDuplicate } = {}) => {
// Save the original id in case the save fails.
const originalId = this.id;
// Read https://github.com/elastic/kibana/issues/9056 and
// https://github.com/elastic/kibana/issues/9012 for some background into why this copyOnSave variable
// exists.
// The goal is to move towards a better rename flow, but since our users have been conditioned
// to expect a 'save as' flow during a rename, we are keeping the logic the same until a better
// UI/UX can be worked out.
if (this.copyOnSave) {
this.id = null;
}
const source = this.serialize();
this.isSaving = true;
return checkForDuplicateTitle(isTitleDuplicateConfirmed, onTitleDuplicate)
.then(() => {
if (confirmOverwrite) {
return createSource(source);
} else {
return savedObjectsClient.create(esType, source, { id: this.id, overwrite: true });
}
})
.then((resp) => {
this.id = resp.id;
})
.then(() => {
if (this.showInRecentlyAccessed && this.getFullPath) {
recentlyAccessed.add(this.getFullPath(), this.title, this.id);
}
this.isSaving = false;
this.lastSavedTitle = this.title;
return this.id;
})
.catch((err) => {
this.isSaving = false;
this.id = originalId;
if (isErrorNonFatal(err)) {
return;
}
return Promise.reject(err);
});
};
this.destroy = () => {
if (this.searchSource) {
this.searchSource.cancelQueued();
}
};
/**
* Delete this object from Elasticsearch
* @return {promise}
*/
this.delete = () => {
return savedObjectsClient.delete(esType, this.id);
};
}
return SavedObject;
}

View File

@ -1,3 +1,4 @@
/* eslint-disable */
/* FileSaver.js
* A saveAs() FileSaver implementation.
* 1.3.8

View File

@ -18,20 +18,20 @@ app
.service('regionmapsConfig', function () {
return {
// Intended noop function and empty array
noop: () => {},
noop() {},
layers: []
}
})
.service('mapConfig', function () {
return {
// Intended noop function
noop: () => {}
noop() {}
}
})
.service('tilemapsConfig', function () {
return {
// Intended noop function and false properties
noop: () => {},
noop() {},
deprecated: {
config: {
options: false

View File

@ -1,7 +1,7 @@
export default {
encode: text => {
if (/([^\u0000-\u00ff])/.test(text)){
const textRegex = /([^\u0000-\u00ff])/; // eslint-disable-line
if (textRegex.test(text)){
throw new Error("Can't base64 encode non-ASCII characters.");
}
@ -46,8 +46,8 @@ export default {
decode: text => {
text = text.replace(/\s/g,"");
if(!(/^[a-z0-9\-_\s]+\={0,2}$/i.test(text)) || text.length % 4 > 0){
const textRegex = /^[a-z0-9\-_\s]+\={0,2}$/i; // eslint-disable-line
if(!(textRegex.test(text)) || text.length % 4 > 0){
throw new Error("Not a base64-encoded string.");
}

View File

@ -9,7 +9,7 @@
*
* Find more information about this on the LICENSE file.
*/
export default class FilterHandler {
export class FilterHandler {
constructor(pattern) {
this.pattern = pattern;
}
@ -36,7 +36,7 @@ export default class FilterHandler {
$state: {
store: 'appState'
}
}
};
}
agentQuery(agent) {
@ -110,7 +110,7 @@ export default class FilterHandler {
result.meta.key = 'rule.pci_dss';
result.exists = {
field: 'rule.pci_dss'
}
};
delete result.query;
return result;
}
@ -122,7 +122,7 @@ export default class FilterHandler {
result.meta.key = 'rule.gdpr';
result.exists = {
field: 'rule.gdpr'
}
};
delete result.query;
return result;
}

View File

@ -22,7 +22,7 @@ export default id => {
html.split('ng-non-bindable')[1].split('>')[1].split('</') &&
html.split('ng-non-bindable')[1].split('>')[1].split('</')[0]) {
return html.split('ng-non-bindable')[1].split('>')[1].split('</')[0]
return html.split('ng-non-bindable')[1].split('>')[1].split('</')[0];
}
@ -40,4 +40,4 @@ export default id => {
}
}
return '';
}
};

View File

@ -18,7 +18,7 @@
* wazuh-reporting 50XX
* unknown 1000
*/
export default (message = null, code = null, statusCode = null, reply) => {
export function ErrorResponse (message = null, code = null, statusCode = null, reply) {
let filteredMessage = '';
if(code) {
const isString = typeof message === 'string';
@ -48,4 +48,4 @@ export default (message = null, code = null, statusCode = null, reply) => {
statusCode: statusCode ? statusCode : 500
})
.code(statusCode ? statusCode : 500);
};
}

View File

@ -9,9 +9,9 @@
*
* Find more information about this on the LICENSE file.
*/
import WazuhElastic from './wazuh-elastic';
import WazuhApiElastic from './wazuh-api-elastic';
import WazuhApi from './wazuh-api';
import WazuhReportingCtrl from './wazuh-reporting';
import { WazuhElasticCtrl } from './wazuh-elastic';
import { WazuhApiElasticCtrl } from './wazuh-api-elastic';
import { WazuhApiCtrl } from './wazuh-api';
import { WazuhReportingCtrl } from './wazuh-reporting';
export { WazuhElastic, WazuhApiElastic, WazuhApi, WazuhReportingCtrl };
export { WazuhElasticCtrl, WazuhApiElasticCtrl, WazuhApiCtrl, WazuhReportingCtrl };

View File

@ -10,9 +10,9 @@
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import ErrorResponse from './error-response';
import log from '../logger';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import { ErrorResponse } from './error-response';
import { log } from '../logger';
const userRegEx = new RegExp(/^.{3,100}$/);
const passRegEx = new RegExp(/^.{3,100}$/);
@ -20,7 +20,7 @@ const urlRegEx = new RegExp(/^https?:\/\/[a-zA-Z0-9-.]{1,300}$/);
const urlRegExIP = new RegExp(/^https?:\/\/[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$/);
const portRegEx = new RegExp(/^[0-9]{2,5}$/);
export default class WazuhApiElastic {
export class WazuhApiElasticCtrl {
constructor(server) {
this.wzWrapper = new ElasticWrapper(server);
}

View File

@ -14,23 +14,23 @@
import needle from 'needle';
import pciRequirementsFile from '../integration-files/pci-requirements';
import gdprRequirementsFile from '../integration-files/gdpr-requirements';
import ElasticWrapper from '../lib/elastic-wrapper';
import getPath from '../../util/get-path';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import { getPath } from '../../util/get-path';
import packageInfo from '../../package.json';
import monitoring from '../monitoring';
import ErrorResponse from './error-response';
import { Monitoring } from '../monitoring';
import { ErrorResponse } from './error-response';
import { Parser } from 'json2csv';
import getConfiguration from '../lib/get-configuration';
import { getConfiguration } from '../lib/get-configuration';
import { totalmem } from 'os';
import simpleTail from 'simple-tail';
import path from 'path';
import log from '../logger';
import { log } from '../logger';
import CsvKeys from '../../util/csv-key-equivalence';
export default class WazuhApi {
export class WazuhApiCtrl {
constructor(server){
this.wzWrapper = new ElasticWrapper(server);
this.fetchAgentsExternal = monitoring(server,{disableCron:true})
this.fetchAgentsExternal = Monitoring(server,{disableCron:true})
}
async checkStoredAPI (req, reply) {

View File

@ -9,9 +9,9 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import ErrorResponse from './error-response';
import log from '../logger';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import { ErrorResponse } from './error-response';
import { log } from '../logger';
import {
AgentsVisualizations,
@ -20,7 +20,7 @@ import {
} from '../integration-files/visualizations';
export default class WazuhElastic {
export class WazuhElasticCtrl {
constructor(server){
this.wzWrapper = new ElasticWrapper(server);
}

View File

@ -9,31 +9,35 @@
*
* Find more information about this on the LICENSE file.
*/
import path from 'path';
import fs from 'fs';
import descriptions from '../reporting/tab-description';
import * as TimSort from 'timsort';
import rawParser from '../reporting/raw-parser';
import PdfPrinter from 'pdfmake/src/printer';
import ErrorResponse from './error-response';
import VulnerabilityRequest from '../reporting/vulnerability-request';
import OverviewRequest from '../reporting/overview-request';
import RootcheckRequest from '../reporting/rootcheck-request';
import PciRequest from '../reporting/pci-request';
import GdprRequest from '../reporting/gdpr-request';
import AuditRequest from '../reporting/audit-request';
import SyscheckRequest from '../reporting/syscheck-request';
import PCI from '../integration-files/pci-requirements-pdfmake';
import GDPR from '../integration-files/gdpr-requirements-pdfmake';
import PdfTable from '../reporting/generic-table';
import WazuhApi from './wazuh-api';
import clockIconRaw from '../reporting/clock-icon-raw';
import filterIconRaw from '../reporting/filter-icon-raw';
import { AgentsVisualizations, OverviewVisualizations } from '../integration-files/visualizations';
import path from 'path';
import fs from 'fs';
import descriptions from '../reporting/tab-description';
import * as TimSort from 'timsort';
import rawParser from '../reporting/raw-parser';
import PdfPrinter from 'pdfmake/src/printer';
import { ErrorResponse } from './error-response';
import { VulnerabilityRequest } from '../reporting/vulnerability-request';
import { OverviewRequest } from '../reporting/overview-request';
import { RootcheckRequest } from '../reporting/rootcheck-request';
import { PciRequest } from '../reporting/pci-request';
import { GdprRequest } from '../reporting/gdpr-request';
import { AuditRequest } from '../reporting/audit-request';
import { SyscheckRequest } from '../reporting/syscheck-request';
import PCI from '../integration-files/pci-requirements-pdfmake';
import GDPR from '../integration-files/gdpr-requirements-pdfmake';
import PdfTable from '../reporting/generic-table';
import { WazuhApiCtrl } from './wazuh-api';
import clockIconRaw from '../reporting/clock-icon-raw';
import filterIconRaw from '../reporting/filter-icon-raw';
import {
AgentsVisualizations,
OverviewVisualizations
} from '../integration-files/visualizations';
const REPORTING_PATH = '../../../../optimize/wazuh-reporting';
export default class WazuhReportingCtrl {
export class WazuhReportingCtrl {
constructor(server) {
this.server = server;
this.fonts = {
@ -103,7 +107,7 @@ export default class WazuhReportingCtrl {
content: [
],
footer: function (currentPage, pageCount) {
footer (currentPage, pageCount) {
return {
columns: [
{
@ -115,7 +119,7 @@ export default class WazuhReportingCtrl {
]
};
},
pageBreakBefore: function (currentNode, followingNodesOnPage, nodesOnNextPage, previousNodesOnPage) {
pageBreakBefore (currentNode, followingNodesOnPage) {
if (currentNode.id && currentNode.id.includes('splitvis')) {
return followingNodesOnPage.length === 6 || followingNodesOnPage.length === 7;
}
@ -129,7 +133,7 @@ export default class WazuhReportingCtrl {
}
};
this.apiRequest = new WazuhApi(server);
this.apiRequest = new WazuhApiCtrl(server);
}
renderTables(tables) {
@ -151,19 +155,14 @@ export default class WazuhReportingCtrl {
const modifiedRows = [];
for (const row of rows) {
modifiedRows.push(row.map(cell => {
return { text: cell, style: 'standard' };
}));
modifiedRows.push(row.map(cell => ({ text: cell, style: 'standard' })));
}
const widths = Array(table.columns.length - 1).fill('auto');
widths.push('*');
full_body.push(
table.columns.map(col => {
return { text: col, style: 'whiteColor', border: [0, 0, 0, 0] };
})
, ...modifiedRows);
table.columns.map(col => ({ text: col, style: 'whiteColor', border: [0, 0, 0, 0]})), ...modifiedRows);
this.dd.content.push({
fontSize: 8,
table: {
@ -586,7 +585,7 @@ export default class WazuhReportingCtrl {
if (section === 'agents' && tab === 'pm') {
const database = await this.apiRequest.makeGenericRequest('GET', `/rootcheck/${agent}`, { limit: 15 }, apiId);
const cis = await this.apiRequest.makeGenericRequest('GET', `/rootcheck/${agent}/cis`, {}, apiId);
//const cis = await this.apiRequest.makeGenericRequest('GET', `/rootcheck/${agent}/cis`, {}, apiId);
const pci = await this.apiRequest.makeGenericRequest('GET', `/rootcheck/${agent}/pci`, {}, apiId);
const lastScan = await this.apiRequest.makeGenericRequest('GET', `/rootcheck/${agent}/last_scan`, {}, apiId);
@ -727,7 +726,7 @@ export default class WazuhReportingCtrl {
for (const critical of topCriticalPackages) {
customul.push({ text: critical.package, style: 'standard' });
customul.push({
ul: critical.references.map(item => { return { text: item, color: '#1EA5C8' }; })
ul: critical.references.map(item => ({ text: item, color: '#1EA5C8' }))
});
}
this.dd.content.push({ ul: customul })
@ -744,7 +743,7 @@ export default class WazuhReportingCtrl {
for (const critical of topHighPackages) {
customul.push({ text: critical.package, style: 'standard' });
customul.push({
ul: critical.references.map(item => { return { text: item, color: '#1EA5C8' }; })
ul: critical.references.map(item => ({ text: item, color: '#1EA5C8' }))
});
}
customul && customul.length && this.dd.content.push({ ul: customul });

View File

@ -9,17 +9,17 @@
*
* Find more information about this on the LICENSE file.
*/
import needle from 'needle'
import colors from 'ansicolors'
import log from './logger'
import ElasticWrapper from './lib/elastic-wrapper'
import packageJSON from '../package.json'
import kibana_template from './integration-files/kibana-template'
import getConfiguration from './lib/get-configuration'
import defaultExt from './lib/default-ext'
import { BuildBody } from './lib/replicas-shards-helper'
import needle from 'needle'
import colors from 'ansicolors'
import { log } from './logger'
import { ElasticWrapper } from './lib/elastic-wrapper'
import packageJSON from '../package.json'
import kibana_template from './integration-files/kibana-template'
import { getConfiguration } from './lib/get-configuration'
import defaultExt from './lib/default-ext'
import { BuildBody } from './lib/replicas-shards-helper'
export default (server, options) => {
export function Initialize(server) {
const blueWazuh = colors.blue('wazuh');
// Elastic JS Client
@ -674,4 +674,4 @@ export default (server, options) => {
// Check Kibana index and if it is prepared, start the initialization of Wazuh App.
checkStatus();
};
}

View File

@ -11,19 +11,19 @@
*/
export default [
{
"_id": "Wazuh-App-Agents-PCI-Requirements",
"_source": {
"title": "Requirements",
"visState": "{\"title\":\"Requirements\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"rotate\":0},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rule.pci_dss\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"rule.pci_dss\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"PCI DSS Requirements\"}}]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON":
"{\"index\":\"wazuh-alerts\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
}
},
"_type": "visualization"
"_id": "Wazuh-App-Agents-PCI-Requirements",
"_source": {
"title": "Requirements",
"visState": "{\"title\":\"Requirements\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100,\"rotate\":0},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":\"true\",\"type\":\"histogram\",\"mode\":\"stacked\",\"data\":{\"label\":\"Count\",\"id\":\"1\"},\"valueAxis\":\"ValueAxis-1\",\"drawLinesBetweenPoints\":true,\"showCircles\":true}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"1\",\"enabled\":true,\"type\":\"count\",\"schema\":\"metric\",\"params\":{}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"rule.pci_dss\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"\"}},{\"id\":\"2\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"segment\",\"params\":{\"field\":\"rule.pci_dss\",\"size\":10,\"order\":\"desc\",\"orderBy\":\"1\",\"customLabel\":\"PCI DSS Requirements\"}}]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON":
"{\"index\":\"wazuh-alerts\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
}
},
"_type": "visualization"
},
{
"_id": "Wazuh-App-Agents-PCI-Groups",

View File

@ -14,28 +14,28 @@ export default [
"_id": "Wazuh-App-Cluster-Overview",
"_type": "visualization",
"_source": {
"title": "Wazuh App Cluster Overview",
"visState": "{\"title\":\"Wazuh App Cluster Overview\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*)\",\"interval\":\"auto\"},\"aggs\":[]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"title": "Wazuh App Cluster Overview",
"visState": "{\"title\":\"Wazuh App Cluster Overview\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(*)\",\"interval\":\"auto\"},\"aggs\":[]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"index\":\"wazuh-alerts\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
}
}
}
},
{
"_id": "Wazuh-App-Cluster-Overview-Manager",
"_type": "visualization",
"_source": {
"title": "Wazuh App Cluster Overview Manager",
"visState": "{\"title\":\"Wazuh App Cluster Overview Manager\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q=agent.id:000)\",\"interval\":\"auto\"},\"aggs\":[]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"title": "Wazuh App Cluster Overview Manager",
"visState": "{\"title\":\"Wazuh App Cluster Overview Manager\",\"type\":\"timelion\",\"params\":{\"expression\":\".es(q=agent.id:000)\",\"interval\":\"auto\"},\"aggs\":[]}",
"uiStateJSON": "{}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"index\":\"wazuh-alerts\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
}
}
}
},
{

View File

@ -13,14 +13,14 @@ export default [
{
"_id": "Wazuh-App-Overview-General-Agents-status",
"_source": {
"title": "Agents status",
"visState": "{\"title\":\"Agents Status\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"line\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"cardinal\",\"lineWidth\":3.5,\"data\":{\"id\":\"4\",\"label\":\"Unique count of id\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"h\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"status\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"_term\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"id\"}}]}",
"uiStateJSON": "{\"vis\":{\"colors\":{\"Never connected\":\"#447EBC\",\"Active\":\"#E5AC0E\"}}}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"title": "Agents status",
"visState": "{\"title\":\"Agents Status\",\"type\":\"histogram\",\"params\":{\"type\":\"histogram\",\"grid\":{\"categoryLines\":false,\"style\":{\"color\":\"#eee\"}},\"categoryAxes\":[{\"id\":\"CategoryAxis-1\",\"type\":\"category\",\"position\":\"bottom\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\"},\"labels\":{\"show\":true,\"truncate\":100},\"title\":{}}],\"valueAxes\":[{\"id\":\"ValueAxis-1\",\"name\":\"LeftAxis-1\",\"type\":\"value\",\"position\":\"left\",\"show\":true,\"style\":{},\"scale\":{\"type\":\"linear\",\"mode\":\"normal\"},\"labels\":{\"show\":true,\"rotate\":0,\"filter\":false,\"truncate\":100},\"title\":{\"text\":\"Count\"}}],\"seriesParams\":[{\"show\":true,\"mode\":\"normal\",\"type\":\"line\",\"drawLinesBetweenPoints\":true,\"showCircles\":true,\"interpolate\":\"cardinal\",\"lineWidth\":3.5,\"data\":{\"id\":\"4\",\"label\":\"Unique count of id\"},\"valueAxis\":\"ValueAxis-1\"}],\"addTooltip\":true,\"addLegend\":true,\"legendPosition\":\"right\",\"times\":[],\"addTimeMarker\":false},\"aggs\":[{\"id\":\"2\",\"enabled\":true,\"type\":\"date_histogram\",\"schema\":\"segment\",\"params\":{\"field\":\"@timestamp\",\"interval\":\"h\",\"customInterval\":\"2h\",\"min_doc_count\":1,\"extended_bounds\":{}}},{\"id\":\"3\",\"enabled\":true,\"type\":\"terms\",\"schema\":\"group\",\"params\":{\"field\":\"status\",\"size\":5,\"order\":\"desc\",\"orderBy\":\"_term\"}},{\"id\":\"4\",\"enabled\":true,\"type\":\"cardinality\",\"schema\":\"metric\",\"params\":{\"field\":\"id\"}}]}",
"uiStateJSON": "{\"vis\":{\"colors\":{\"Never connected\":\"#447EBC\",\"Active\":\"#E5AC0E\"}}}",
"description": "",
"version": 1,
"kibanaSavedObjectMeta": {
"searchSourceJSON": "{\"index\":\"wazuh-monitoring-3.x-*\",\"filter\":[],\"query\":{\"query\":\"\",\"language\":\"lucene\"}}"
}
}
},
"_type": "visualization"
},

View File

@ -11,7 +11,7 @@
*/
import knownFields from '../integration-files/known-fields';
export default class ElasticWrapper {
export class ElasticWrapper {
constructor(server){
this.elasticRequest = server.plugins.elasticsearch.getCluster('data');
this.WZ_KIBANA_INDEX = server &&
@ -437,7 +437,7 @@ export default class ElasticWrapper {
} catch(error){
return Promise.reject(error);
}
};
}
/**
* Usually used to save a new Wazuh API entry
@ -526,7 +526,7 @@ export default class ElasticWrapper {
} catch(error){
return Promise.reject(error);
}
};
}
/**
* Same as curling the templates from Elasticsearch

View File

@ -13,7 +13,7 @@ import fs from 'fs'
import yml from 'js-yaml'
import path from 'path'
export default () => {
export function getConfiguration() {
try {
const customPath = path.join(__dirname, '../../config.yml');
const raw = fs.readFileSync(customPath, { encoding: 'utf-8' })

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import log from '../logger'
import cron from 'node-cron'
import { log } from '../logger'
import cron from 'node-cron'
export default interval => {
export function parseCron(interval) {
try {
if(!interval) throw new Error('Interval not found');

View File

@ -97,7 +97,7 @@ const checkFiles = () => {
* @param {*} message Message to show
* @param {*} level Optional, default is 'error'
*/
export default (location, message, level) => {
export function log(location, message, level) {
initDirectory()
.then(() => {
if(allowed){
@ -110,5 +110,5 @@ export default (location, message, level) => {
});
}
})
.catch(error => console.error(`Cannot create the logs directory due to:\n${error.message || error}`));
};
.catch(error => console.error(`Cannot create the logs directory due to:\n${error.message || error}`)); // eslint-disable-line
}

View File

@ -9,19 +9,19 @@
*
* Find more information about this on the LICENSE file.
*/
import cron from 'node-cron'
import needle from 'needle'
import getPath from'../util/get-path'
import colors from 'ansicolors'
import log from './logger'
import ElasticWrapper from './lib/elastic-wrapper'
import monitoringTemplate from './integration-files/monitoring-template'
import packageJSON from '../package.json'
import getConfiguration from './lib/get-configuration'
import parseCron from './lib/parse-cron'
import { BuildBody } from './lib/replicas-shards-helper'
import cron from 'node-cron'
import needle from 'needle'
import { getPath } from'../util/get-path'
import colors from 'ansicolors'
import { log } from './logger'
import { ElasticWrapper } from './lib/elastic-wrapper'
import monitoringTemplate from './integration-files/monitoring-template'
import packageJSON from '../package.json'
import { getConfiguration } from './lib/get-configuration'
import { parseCron } from './lib/parse-cron'
import { BuildBody } from './lib/replicas-shards-helper'
export default (server, options) => {
export function Monitoring (server, options) {
const blueWazuh = colors.blue('wazuh');
let ENABLED = true;
@ -280,7 +280,7 @@ export default (server, options) => {
}
if (body === '') return;
const response = await wzWrapper.pushBulkAnyIndex(todayIndex,body);
await wzWrapper.pushBulkAnyIndex(todayIndex,body);
agentsArray.length = 0;
}
@ -341,7 +341,7 @@ export default (server, options) => {
try {
log('[monitoring][checkTemplate]', 'Updating wazuh-monitoring template...', 'info');
server.log([blueWazuh, 'monitoring', 'info'], "Updating wazuh-monitoring template...");
const data = await wzWrapper.putMonitoringTemplate(monitoringTemplate);
await wzWrapper.putMonitoringTemplate(monitoringTemplate);
return;
} catch(error){
log('[monitoring][checkTemplate]', `Something went wrong updating wazuh-monitoring template... ${error.message || error}`);
@ -452,4 +452,4 @@ export default (server, options) => {
// Cron tab for getting agent status.
if(!options && ENABLED) cron.schedule(CRON_FREQ, cronTask, true);
return fetchAgentsExternal;
};
}

View File

@ -9,11 +9,11 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
import AuditMap from './audit-map';
export default class PciRequest {
export class AuditRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana
@ -176,7 +176,7 @@ export default class PciRequest {
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const { buckets } = response.aggregations['2'];
return buckets.map(item => { return { id:item.key, syscall:AuditMap[item.key] };});
return buckets.map(item => ({ id:item.key, syscall:AuditMap[item.key] }));
} catch (error) {
return Promise.reject(error);

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class GdprRequest {
export class GdprRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class VulnerabilityRequest {
export class OverviewRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class PciRequest {
export class PciRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class RootcheckRequest {
export class RootcheckRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class SyscheckRequest {
export class SyscheckRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana

View File

@ -9,10 +9,10 @@
*
* Find more information about this on the LICENSE file.
*/
import ElasticWrapper from '../lib/elastic-wrapper';
import { ElasticWrapper } from '../lib/elastic-wrapper';
import Base from './base-query';
export default class VulnerabilityRequest {
export class VulnerabilityRequest {
/**
* Constructor
* @param {*} server Hapi.js server object provided by Kibana
@ -174,7 +174,7 @@ export default class VulnerabilityRequest {
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const { buckets } = response.aggregations['2'];
return buckets.map(item => {return {package: item.key, severity: severity};});
return buckets.map(item => ({package: item.key, severity: severity}));
} catch (error) {
return Promise.reject(error);
@ -221,17 +221,13 @@ export default class VulnerabilityRequest {
const response = await this.wzWrapper.searchWazuhAlertsWithPayload(base);
const { buckets } = response.aggregations['2'];
return buckets.map(item => {
return {
package: item.key,
references: item['3'].buckets.map(ref => ref.key)
};
});
return buckets.map(item => ({
package: item.key,
references: item['3'].buckets.map(ref => ref.key)
}));
} catch (error) {
return Promise.reject(error);
}
}
}

View File

@ -9,26 +9,26 @@
*
* Find more information about this on the LICENSE file.
*/
import { WazuhApiElastic } from '../controllers';
import { WazuhApiElasticCtrl } from '../controllers';
export default (server, options) => {
const ctrl = new WazuhApiElastic(server);
export function WazuhApiElasticRoutes(server) {
const ctrl = new WazuhApiElasticCtrl(server);
// Save the given API into elasticsearch
server.route({ method: 'PUT', path: '/api/wazuh-api/settings', handler: (req,reply) => ctrl.saveAPI(req,reply) });
server.route({ method: 'PUT', path: '/api/wazuh-api/settings', handler(req, reply) { return ctrl.saveAPI(req, reply) } });
// Update the given API into elasticsearch
server.route({ method: 'PUT', path: '/api/wazuh-api/update-settings', handler: (req,reply) => ctrl.updateFullAPI(req,reply) });
server.route({ method: 'PUT', path: '/api/wazuh-api/update-settings', handler(req, reply) { return ctrl.updateFullAPI(req, reply) } });
// Get Wazuh-API entries list (Multimanager) from elasticsearch index
server.route({ method: 'GET', path: '/api/wazuh-api/apiEntries', handler: (req,reply) => ctrl.getAPIEntries(req,reply) });
server.route({ method: 'GET', path: '/api/wazuh-api/apiEntries', handler(req, reply) { return ctrl.getAPIEntries(req, reply) } });
// Delete Wazuh-API entry (multimanager) from elasticsearch index
server.route({ method: 'DELETE', path: '/api/wazuh-api/apiEntries/{id}', handler: (req,reply) => ctrl.deleteAPIEntries(req,reply) });
server.route({ method: 'DELETE', path: '/api/wazuh-api/apiEntries/{id}', handler(req, reply) { return ctrl.deleteAPIEntries(req, reply) } });
// Set Wazuh-API as default (multimanager) on elasticsearch index
server.route({ method: 'PUT', path: '/api/wazuh-api/apiEntries/{id}', handler: (req,reply) => ctrl.setAPIEntryDefault(req,reply) });
server.route({ method: 'PUT', path: '/api/wazuh-api/apiEntries/{id}', handler(req, reply) { return ctrl.setAPIEntryDefault(req, reply) } });
// Update the API hostname
server.route({ method: 'PUT', path: '/api/wazuh-api/updateApiHostname/{id}', handler: (req,reply) => ctrl.updateAPIHostname(req,reply) });
};
server.route({ method: 'PUT', path: '/api/wazuh-api/updateApiHostname/{id}', handler(req, reply) { return ctrl.updateAPIHostname(req, reply) } });
}

View File

@ -9,42 +9,42 @@
*
* Find more information about this on the LICENSE file.
*/
import { WazuhApi } from '../controllers';
import { WazuhApiCtrl } from '../controllers';
export default (server, options) => {
const ctrl = new WazuhApi(server);
export function WazuhApiRoutes (server) {
const ctrl = new WazuhApiCtrl(server);
// Returns if the wazuh-api configuration is working
server.route({ method: 'POST', path: '/api/wazuh-api/checkStoredAPI', handler: (req, reply) => ctrl.checkStoredAPI(req, reply) });
server.route({ method: 'POST', path: '/api/wazuh-api/checkStoredAPI', handler(req, reply) { return ctrl.checkStoredAPI(req, reply)} });
// Check if credentials on POST connect to Wazuh API. Not storing them!
// Returns if the wazuh-api configuration received in the POST body will work
server.route({ method: 'POST', path: '/api/wazuh-api/checkAPI', handler: (req, reply) => ctrl.checkAPI(req, reply) });
server.route({ method: 'POST', path: '/api/wazuh-api/checkAPI', handler(req, reply) { return ctrl.checkAPI(req, reply) }});
// Returns the request result (With error control)
server.route({ method: 'POST', path: '/api/wazuh-api/request', handler: (req, reply) => ctrl.requestApi(req, reply) });
server.route({ method: 'POST', path: '/api/wazuh-api/request', handler(req, reply) { return ctrl.requestApi(req, reply) }});
// Return a PCI requirement description
server.route({ method: 'GET', path: '/api/wazuh-api/pci/{requirement}', handler: (req, reply) => ctrl.getPciRequirement(req, reply) });
server.route({ method: 'GET', path: '/api/wazuh-api/pci/{requirement}', handler(req, reply) { return ctrl.getPciRequirement(req, reply) }});
// Return a GDPR requirement description
server.route({ method: 'GET', path: '/api/wazuh-api/gdpr/{requirement}', handler: (req, reply) => ctrl.getGdprRequirement(req, reply) });
server.route({ method: 'GET', path: '/api/wazuh-api/gdpr/{requirement}', handler(req, reply) { return ctrl.getGdprRequirement(req, reply)} });
// Force fetch data to be inserted on wazuh-monitoring indices
server.route({ method: 'GET', path: '/api/wazuh-api/fetchAgents', handler: (req, reply) => ctrl.fetchAgents(req, reply) });
server.route({ method: 'GET', path: '/api/wazuh-api/fetchAgents', handler(req, reply) { return ctrl.fetchAgents(req, reply) }});
// Returns the config.yml file parsed
server.route({ method: 'GET', path: '/api/wazuh-api/configuration', handler: (req, reply) => ctrl.getConfigurationFile(req, reply) });
server.route({ method: 'GET', path: '/api/wazuh-api/configuration', handler(req, reply) { return ctrl.getConfigurationFile(req, reply)} });
// Returns data from the Wazuh API on CSV readable format
server.route({ method: 'POST', path: '/api/wazuh-api/csv', handler: (req,res) => ctrl.csv(req,res)})
server.route({ method: 'POST', path: '/api/wazuh-api/csv', handler(req,res) { return ctrl.csv(req,res)}})
// Returns total RAM available from the current machine where Kibana is being executed
server.route({ method: 'GET', path: '/api/wazuh-api/ram', handler: (req,res) => ctrl.totalRam(req,res)})
server.route({ method: 'GET', path: '/api/wazuh-api/ram', handler(req,res) { return ctrl.totalRam(req,res)}})
// Returns unique fields from the agents such OS, agent version ...
server.route({ method: 'GET', path: '/api/wazuh-api/agents-unique/{api}', handler: (req,res) => ctrl.getAgentsFieldsUniqueCount(req,res)});
server.route({ method: 'GET', path: '/api/wazuh-api/agents-unique/{api}', handler(req,res) { return ctrl.getAgentsFieldsUniqueCount(req,res)}});
// Returns Wazuh app logs ...
server.route({ method: 'GET', path: '/api/wazuh-api/logs', handler: (req,res) => ctrl.getAppLogs(req,res)});
};
server.route({ method: 'GET', path: '/api/wazuh-api/logs', handler(req,res) { return ctrl.getAppLogs(req,res)}});
}

View File

@ -9,34 +9,34 @@
*
* Find more information about this on the LICENSE file.
*/
import { WazuhElastic } from '../controllers';
import { WazuhElasticCtrl } from '../controllers';
export default (server, options) => {
const ctrl = new WazuhElastic(server);
export function WazuhElasticRouter(server) {
const ctrl = new WazuhElasticCtrl(server);
// Get index patterns list
server.route({ method: 'GET', path: '/get-list', handler: (req,res) => ctrl.getlist(req,res) });
server.route({ method: 'GET', path: '/get-list', handler(req, res) { return ctrl.getlist(req, res) } });
// Refresh known fields for specific index pattern
server.route({ method: 'GET', path: '/refresh-fields/{pattern}', handler: (req,res) => ctrl.refreshIndex(req,res) });
server.route({ method: 'GET', path: '/refresh-fields/{pattern}', handler(req, res) { return ctrl.refreshIndex(req, res) } });
// Create visualizations specified in 'tab' parameter and applying to 'pattern'
server.route({ method: 'GET', path: '/api/wazuh-elastic/create-vis/{tab}/{pattern}', handler: (req,res) => ctrl.createVis(req,res) });
server.route({ method: 'POST', path: '/api/wazuh-elastic/create-vis/{tab}/{pattern}', handler: (req,res) => ctrl.createClusterVis(req,res) });
server.route({ method: 'GET', path: '/api/wazuh-elastic/create-vis/{tab}/{pattern}', handler(req, res) { return ctrl.createVis(req, res) } });
server.route({ method: 'POST', path: '/api/wazuh-elastic/create-vis/{tab}/{pattern}', handler(req, res) { return ctrl.createClusterVis(req, res) } });
// Returns whether a correct template is being applied for the index-pattern
server.route({ method: 'GET', path: '/api/wazuh-elastic/template/{pattern}', handler: (req,res) => ctrl.getTemplate(req,res) });
server.route({ method: 'GET', path: '/api/wazuh-elastic/template/{pattern}', handler(req, res) { return ctrl.getTemplate(req, res) } });
// Returns whether the pattern exists or not
server.route({ method: 'GET', path: '/api/wazuh-elastic/pattern/{pattern}', handler: (req,res) => ctrl.checkPattern(req,res) });
server.route({ method: 'GET', path: '/api/wazuh-elastic/pattern/{pattern}', handler(req, res) { return ctrl.checkPattern(req, res) } });
// Returns the agent with most alerts
server.route({ method: 'GET', path: '/api/wazuh-elastic/top/{mode}/{cluster}/{field}/{pattern}', handler: (req,res) => ctrl.getFieldTop(req,res) });
server.route({ method: 'GET', path: '/api/wazuh-elastic/top/{mode}/{cluster}/{field}/{pattern}', handler(req, res) { return ctrl.getFieldTop(req, res) } });
// Return Wazuh Appsetup info
server.route({ method: 'GET', path: '/api/wazuh-elastic/setup', handler: (req,res) => ctrl.getSetupInfo(req,res) });
server.route({ method: 'GET', path: '/api/wazuh-elastic/setup', handler(req, res) { return ctrl.getSetupInfo(req, res) } });
// Useful to check cookie consistence
server.route({ method: 'GET', path: '/api/wazuh-elastic/timestamp', handler: (req,res) => ctrl.getTimeStamp(req,res) });
};
server.route({ method: 'GET', path: '/api/wazuh-elastic/timestamp', handler(req, res) { return ctrl.getTimeStamp(req, res) } });
}

View File

@ -11,18 +11,18 @@
*/
import { WazuhReportingCtrl } from '../controllers';
export default (server, options) => {
export function WazuhReportingRoutes(server) {
const ctrl = new WazuhReportingCtrl(server);
// Builds a PDF report from multiple PNG images
server.route({ method: 'POST', path: '/api/wazuh-reporting/report', handler: (req,res) => ctrl.report(req,res)});
server.route({ method: 'POST', path: '/api/wazuh-reporting/report', handler(req, res) { return ctrl.report(req, res) } });
// Fetch specific report
server.route({ method: 'GET', path: '/api/wazuh-reporting/report/{name}', handler: (req,res) => ctrl.getReportByName(req,res)});
server.route({ method: 'GET', path: '/api/wazuh-reporting/report/{name}', handler(req, res) { return ctrl.getReportByName(req, res) } });
// Delete specific report
server.route({ method: 'DELETE', path: '/api/wazuh-reporting/report/{name}', handler: (req,res) => ctrl.deleteReportByName(req,res)});
server.route({ method: 'DELETE', path: '/api/wazuh-reporting/report/{name}', handler(req, res) { return ctrl.deleteReportByName(req, res) } });
// Fetch the reports list
server.route({ method: 'GET', path: '/api/wazuh-reporting/reports', handler: (req,res) => ctrl.getReports(req,res)});
};
server.route({ method: 'GET', path: '/api/wazuh-reporting/reports', handler(req, res) { return ctrl.getReports(req, res) } });
}

View File

@ -0,0 +1,116 @@
const chai = require('chai');
const needle = require('needle')
chai.should();
const headers = {headers: {'kbn-xsrf': 'kibana', 'Content-Type': 'application/json'}}
let API_ID = null;
let API_PORT = null;
let API_URL = null;
let API_USER = null;
const EXAMPLE_API = {};
describe('wazuh-api-elastic', () => {
/*
// Save the given API into elasticsearch
server.route({ method: 'PUT', path: '/api/wazuh-api/settings', handler: (req,reply) => ctrl.saveAPI(req,reply) });
// Update the given API into elasticsearch
server.route({ method: 'PUT', path: '/api/wazuh-api/update-settings', handler: (req,reply) => ctrl.updateFullAPI(req,reply) });
// Get Wazuh-API entries list (Multimanager) from elasticsearch index
server.route({ method: 'GET', path: '/api/wazuh-api/apiEntries', handler: (req,reply) => ctrl.getAPIEntries(req,reply) });
// Delete Wazuh-API entry (multimanager) from elasticsearch index
server.route({ method: 'DELETE', path: '/api/wazuh-api/apiEntries/{id}', handler: (req,reply) => ctrl.deleteAPIEntries(req,reply) });
// Set Wazuh-API as default (multimanager) on elasticsearch index
server.route({ method: 'PUT', path: '/api/wazuh-api/apiEntries/{id}', handler: (req,reply) => ctrl.setAPIEntryDefault(req,reply) });
// Update the API hostname
server.route({ method: 'PUT', path: '/api/wazuh-api/updateApiHostname/{id}', handler: (req,reply) => ctrl.updateAPIHostname(req,reply) });
*/
before(async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/apiEntries`, {}, {});
if(!res.body || !res.body.length) {
console.log('There are no APIs stored in Elasticsearch, exiting...')
process.exit(1)
}
API_ID = res.body[0]._id;
API_URL = res.body[0]._source.url;
API_PORT = res.body[0]._source.api_port;
API_USER = res.body[0]._source.api_user;
})
it('PUT /api/wazuh-api/settings', async () => {
const res = await needle('put', `localhost:5601/api/wazuh-api/settings`, {
user : 'foo',
password : 'bar',
url : 'http://localhost',
port : 55000,
insecure : true,
component : 'API',
active : true,
cluster_info: {},
extensions : {}
}, headers);
res.body.response.result.should.be.eql('created')
const removed = await needle('delete', `localhost:5601/api/wazuh-api/apiEntries/${res.body.response._id}`, {}, headers);
removed.body.result.should.be.eql('deleted')
})
it('PUT /api/wazuh-api/update-settings', async () => {
const res = await needle('put', `localhost:5601/api/wazuh-api/settings`, {
user : 'foo',
password : 'bar',
url : 'http://localhost',
port : 55000,
insecure : true,
component : 'API',
active : true,
cluster_info: {},
extensions : {}
}, headers);
const updated = await needle('put', `localhost:5601/api/wazuh-api/update-settings`, {user: 'john', password: 'bar', url: 'http://0.0.0.0', port: 55000, id: res.body.response._id}, headers);
await needle('delete', `localhost:5601/api/wazuh-api/apiEntries/${res.body.response._id}`, {}, headers);
updated.body.statusCode.should.be.eql(200)
updated.body.message.should.be.eql('ok')
})
it('GET /api/wazuh-api/apiEntries', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/apiEntries`, {}, headers);
res.body.should.be.a('array')
res.body.length.should.be.gt(0)
})
it('DELETE /api/wazuh-api/apiEntries/{id}', async () => {
const insert = await needle('put', `localhost:5601/api/wazuh-api/settings`, {
user : 'foo',
password : 'bar',
url : 'http://localhost',
port : 55000,
insecure : true,
component : 'API',
active : true,
cluster_info: {},
extensions : {}
}, headers);
const res = await needle('delete', `localhost:5601/api/wazuh-api/apiEntries/${insert.body.response._id}`, {}, headers);
res.body.result.should.be.eql('deleted')
})
it('PUT /api/wazuh-api/apiEntries/{id}', async () => {
const res = await needle('put', `localhost:5601/api/wazuh-api/apiEntries/${API_ID}`, {}, headers);
res.body.statusCode.should.be.eql(200)
res.body.message.should.be.eql('ok')
})
it('PUT /api/wazuh-api/updateApiHostname/{id}', async () => {
const res = await needle('put', `localhost:5601/api/wazuh-api/updateApiHostname/${API_ID}`, {}, headers);
res.body.statusCode.should.be.eql(200)
res.body.message.should.be.eql('ok')
})
})

108
test/server/wazuh-api.js Normal file
View File

@ -0,0 +1,108 @@
const chai = require('chai');
const needle = require('needle')
chai.should();
const headers = {headers: {'kbn-xsrf': 'kibana', 'Content-Type': 'application/json'}}
let API_ID = null;
let API_PORT = null;
let API_URL = null;
let API_USER = null;
describe('wazuh-api', () => {
before(async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/apiEntries`, {}, {});
if(!res.body || !res.body.length) {
console.log('There are no APIs stored in Elasticsearch, exiting...')
process.exit(1)
}
API_ID = res.body[0]._id;
API_URL = res.body[0]._source.url;
API_PORT = res.body[0]._source.api_port;
API_USER = res.body[0]._source.api_user;
})
it('POST /api/wazuh-api/csv', async () => {
const res = await needle('post', `localhost:5601/api/wazuh-api/csv`, {path:'/agents', id: API_ID}, headers);
res.body.should.be.a('string')
})
it('POST /api/wazuh-api/checkAPI', async () => {
const res = await needle('post', `localhost:5601/api/wazuh-api/checkAPI`, {user:API_USER, url:API_URL, port:API_PORT, id:API_ID}, headers);
res.body.should.be.a('object')
res.body.manager.should.be.a('string')
res.body.cluster.should.be.a('string')
res.body.status.should.be.a('string')
})
it('POST /api/wazuh-api/checkStoredAPI', async () => {
const res = await needle('post', `localhost:5601/api/wazuh-api/checkStoredAPI`, API_ID, headers);
res.body.should.be.a('object')
res.body.statusCode.should.be.eql(200)
res.body.data.should.be.a('object')
res.body.data.user.should.be.a('string')
res.body.data.password.should.be.a('string')
res.body.data.url.should.be.a('string')
res.body.data.port.should.be.a('string')
res.body.data.extensions.should.be.a('object')
res.body.data.cluster_info.should.be.a('object')
})
it('POST /api/wazuh-api/request', async () => {
const res = await needle('post', `localhost:5601/api/wazuh-api/request`, {method:'GET', path:'/agents/000', body:{ }, id:API_ID }, headers);
res.body.should.be.a('object')
res.body.error.should.be.eql(0)
res.body.data.should.be.a('object')
res.body.data.status.should.be.eql('Active')
res.body.data.id.should.be.eql('000')
})
it('GET /api/wazuh-api/pci/{requirement}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/pci/all`, {}, {});
res.body.should.be.a('object')
res.body['1.1.1'].should.be.eql('A formal process for approving and testing all network connections and changes to the firewall and router configurations')
})
it('GET /api/wazuh-api/gdpr/{requirement}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/gdpr/all`, {}, {});
res.body.should.be.a('object')
res.body['II_5.1.f'].should.be.eql('Ensure the ongoing confidentiality, integrity, availability and resilience of processing systems and services, verifying its modifications, accesses, locations and guarantee the safety of them.<br>File sharing protection and file sharing technologies that meet the requirements of data protection.')
})
it('GET /api/wazuh-api/configuration', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/configuration`, {}, {});
res.body.should.be.a('object')
res.body.error.should.be.eql(0)
res.body.statusCode.should.be.eql(200)
res.body.data.should.be.a('object')
})
it('GET /api/wazuh-api/ram', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/ram`, {}, {});
res.body.should.be.a('object')
res.body.error.should.be.eql(0)
res.body.ram.should.be.gt(1)
})
it('GET /api/wazuh-api/agents-unique/{api}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/agents-unique/${API_ID}`, {}, {});
res.body.should.be.a('object')
res.body.error.should.be.eql(0)
res.body.result.should.be.a('object')
res.body.result.groups.should.be.a('array')
res.body.result.nodes.should.be.a('array')
res.body.result.versions.should.be.a('array')
res.body.result.osPlatforms.should.be.a('array')
res.body.result.lastAgent.should.be.a('object')
res.body.result.summary.should.be.a('object')
})
it('GET /api/wazuh-api/logs', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-api/logs`, {}, {});
res.body.should.be.a('object')
res.body.lastLogs.should.be.a('array')
res.body.error.should.be.eql(0)
})
})

View File

@ -0,0 +1,91 @@
const chai = require('chai');
const needle = require('needle')
chai.should();
const headers = {headers: {'kbn-xsrf': 'kibana', 'Content-Type': 'application/json'}}
describe('wazuh-elastic', () => {
describe('Checking index patterns', () => {
it('GET /get-list', async () => {
const res = await needle('get', `localhost:5601/get-list`, {}, headers);
res.body.data.should.be.a('array')
res.body.data.length.should.be.gt(0)
res.body.data[0].should.be.a('object')
res.body.data[0].id.should.be.a('string')
res.body.data[0].title.should.be.a('string')
})
it('GET /refresh-fields/{pattern}', async () => {
const res = await needle('get', `localhost:5601/refresh-fields/wazuh-alerts-3.x-*`, {}, headers);
res.body.acknowledge.should.be.eql(true)
res.body.output.should.be.a('object')
res.body.output._index.should.be.eql('.kibana')
res.body.output._type.should.be.eql('doc')
res.body.output._id.should.be.eql('index-pattern:wazuh-alerts-3.x-*')
})
})
describe('Checking visualization composers', () => {
it('GET /api/wazuh-elastic/create-vis/{tab}/{pattern}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-elastic/create-vis/overview-general/wazuh-alerts-3.x-*`, {}, headers);
res.body.acknowledge.should.be.eql(true)
res.body.raw.should.be.a('array')
res.body.raw.length.should.be.eql(15)
res.body.raw[0].attributes.should.be.a('object')
res.body.raw[0].type.should.be.eql('visualization')
res.body.raw[0].id.should.be.a('string')
})
it('POST /api/wazuh-elastic/create-vis/{tab}/{pattern}', async () => {
const res = await needle('post', `localhost:5601/api/wazuh-elastic/create-vis/cluster-monitoring/wazuh-alerts-3.x-*`, {nodes:{items:[],name:'node01'}}, headers);
res.body.acknowledge.should.be.eql(true)
res.body.raw.should.be.a('array')
res.body.raw.length.should.be.eql(4)
res.body.raw[0].attributes.should.be.a('object')
res.body.raw[0].type.should.be.eql('visualization')
res.body.raw[0].id.should.be.a('string')
})
})
describe('Checking template and index pattern existance', () => {
it('GET /api/wazuh-elastic/template/{pattern}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-elastic/template/wazuh-alerts-3.x-*`, {}, headers);
res.body.statusCode.should.be.eql(200)
res.body.status.should.be.eql(true)
res.body.data.should.be.eql('Template found for wazuh-alerts-3.x-*')
})
it('GET /api/wazuh-elastic/pattern/{pattern}', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-elastic/pattern/wazuh-alerts-3.x-*`, {}, headers);
res.body.statusCode.should.be.eql(200)
res.body.status.should.be.eql(true)
res.body.data.should.be.eql('Index pattern found')
})
})
/*it('GET /api/wazuh-elastic/top/{mode}/{cluster}/{field}/{pattern}', async () => {
throw Error('Test not implemented...')
})*/
describe('Checking .wazuh-version index', () => {
it('GET /api/wazuh-elastic/setup', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-elastic/setup`, {}, headers);
res.body.statusCode.should.be.eql(200)
res.body.data.should.be.a('object')
res.body.data.name.should.be.eql('Wazuh App')
res.body.data['app-version'].should.be.eql('3.6.0')
res.body.data.revision.should.be.eql('0407')
res.body.data.installationDate.should.be.a('string')
res.body.data.lastRestart.should.be.a('string')
})
it('GET /api/wazuh-elastic/timestamp', async () => {
const res = await needle('get', `localhost:5601/api/wazuh-elastic/timestamp`, {}, headers);
res.body.installationDate.should.be.a('string')
res.body.lastRestart.should.be.a('string')
})
})
})

View File

@ -9,7 +9,7 @@
*
* Find more information about this on the LICENSE file.
*/
export default config => {
export function getPath (config) {
let path = config.url;
let protocol;
if (config.url.startsWith("https://")) {
@ -26,4 +26,4 @@ export default config => {
path = `${config.url}:${config.port}`;
}
return path;
};
}