Merge branch '3.0-rebrand' into dev-groups-sortable

This commit is contained in:
Javier Castro 2017-11-08 12:38:41 +01:00 committed by GitHub
commit 586cebd2d5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
38 changed files with 2150 additions and 1919 deletions

View File

@ -17,7 +17,8 @@
"semi": 2,
"no-console": 0,
"no-process-exit": 0,
"node/no-unpublished-require":0
"node/no-unpublished-require":0,
"node/no-unsupported-features":0
},
"plugins": ["node","async-await"],
"extends": ["eslint:recommended", "plugin:node/recommended"]

16
.travis.yml Normal file
View File

@ -0,0 +1,16 @@
language: node_js
node_js:
- "stable"
- "6"
cache:
directories:
- node_modules
notifications:
email: false
branches:
only:
- "3.0-rebrand"

View File

@ -1,39 +1,39 @@
module.exports = function (kibana) {
return new kibana.Plugin({
id: 'wazuh',
name: 'wazuh',
require: ['kibana', 'elasticsearch'],
uiExports: {
app: {
id: 'wazuh',
title: 'Wazuh',
description: 'Wazuh App for Kibana',
icon: 'plugins/wazuh/img/icon.png',
main: 'plugins/wazuh/app',
injectVars: function (server, options) {
const serverConfig = server.config();
const configuredUrl = server.config().get('tilemap.url');
const isOverridden = typeof configuredUrl === 'string' && configuredUrl !== '';
const tilemapConfig = serverConfig.get('tilemap');
const regionmapsConfig = serverConfig.get('regionmap');
const mapConfig = serverConfig.get('map');
regionmapsConfig.layers = (regionmapsConfig.layers) ? regionmapsConfig.layers : [];
return {
kbnIndex: serverConfig.get('kibana.index'),
esApiVersion: serverConfig.get('elasticsearch.apiVersion'),
esShardTimeout: serverConfig.get('elasticsearch.shardTimeout'),
regionmapsConfig: regionmapsConfig,
mapConfig: mapConfig,
tilemapsConfig: {
deprecated: {
isOverridden: isOverridden,
config: tilemapConfig,
}
module.exports = (kibana) => new kibana.Plugin({
id: 'wazuh',
name: 'wazuh',
require: ['kibana', 'elasticsearch'],
uiExports: {
app: {
id: 'wazuh',
title: 'Wazuh',
description: 'Wazuh App for Kibana',
icon: 'plugins/wazuh/img/icon.png',
main: 'plugins/wazuh/app',
injectVars: (server, options) => {
const serverConfig = server.config();
const configuredUrl = server.config().get('tilemap.url');
const isOverridden = typeof configuredUrl === 'string' && configuredUrl !== '';
const tilemapConfig = serverConfig.get('tilemap');
const regionmapsConfig = serverConfig.get('regionmap');
const mapConfig = serverConfig.get('map');
regionmapsConfig.layers = (regionmapsConfig.layers) ? regionmapsConfig.layers : [];
return {
kbnIndex: serverConfig.get('kibana.index'),
esApiVersion: serverConfig.get('elasticsearch.apiVersion'),
esShardTimeout: serverConfig.get('elasticsearch.shardTimeout'),
regionmapsConfig: regionmapsConfig,
mapConfig: mapConfig,
tilemapsConfig: {
deprecated: {
isOverridden: isOverridden,
config: tilemapConfig
}
};
}
}
};
}
},
init: require('./init.js')
});
};
}
},
init: require('./init.js')
});

12
init.js
View File

@ -1,7 +1,7 @@
module.exports = function (server, options) {
require('./server/initialize.js')(server, options);
require('./server/api/wazuh-elastic.js')(server, options);
require('./server/api/wazuh-api-elastic.js')(server, options);
require('./server/monitoring.js')(server, options);
require('./server/api/wazuh-api.js')(server, options);
module.exports = (server, options) => {
require('./server/initialize.js')(server, options);
require('./server/api/wazuh-elastic.js')(server, options);
require('./server/api/wazuh-api-elastic.js')(server, options);
require('./server/monitoring.js')(server, options);
require('./server/api/wazuh-api.js')(server, options);
};

View File

@ -3,7 +3,7 @@
"version": "3.0.0",
"revision": "0345",
"kibana": {
"version": "6.0.0-rc1"
"version": "6.0.0-rc2"
},
"description": "Wazuh App",
"main": "index.js",

View File

@ -1,5 +1,5 @@
// Require CSS
require('plugins/wazuh/less/main.less');
require('plugins/wazuh/less/loader');
require('plugins/wazuh/less/ui_framework.less');
// Set up Wazuh app

View File

@ -1,243 +1,312 @@
import rison from 'rison-node';
// Require config
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
// We are using the DataHandler template and customize its path to get information about agents
app.factory('AgentsAutoComplete', function(DataHandler) {
var AgentsAutoComplete = new DataHandler();
app.factory('AgentsAutoComplete', function (DataHandler) {
let AgentsAutoComplete = new DataHandler();
AgentsAutoComplete.path = '/agents';
return AgentsAutoComplete;
});
app.controller('agentsController', function ($scope, $q, $routeParams, $route, $location, $rootScope, Notifier, appState, genericReq, apiReq, AgentsAutoComplete) {
const notify = new Notifier({location: 'Agents'});
$rootScope.page = "agents";
$scope.submenuNavItem = 'preview';
app.controller('agentsController',
function ($scope, $q, $routeParams, $route, $location, $rootScope, Notifier, appState, genericReq, apiReq, AgentsAutoComplete) {
$scope.agentsAutoComplete = AgentsAutoComplete;
const notify = new Notifier({ location: 'Agents' });
$rootScope.page = 'agents';
$scope.submenuNavItem = 'preview';
$scope.agentsAutoComplete = AgentsAutoComplete;
if ($location.search().tabView)
if ($location.search().tabView){
$scope.tabView = $location.search().tabView;
else {
} else {
$scope.tabView = "panels";
$location.search("tabView", "panels");
}
$scope.hideRing = function(items) {
if($(".vis-editor-content" ).length >= items)
return true;
return false;
}
$scope.hideRing = (items) => $(".vis-editor-content").length >= items;
// Object for matching nav items and Wazuh groups
var tabGroups = { "overview": {"group": "*"}, "fim": {"group": "syscheck"}, "policy_monitoring": {"group": "rootcheck"}, "oscap": {"group": "oscap"}, "audit": {"group": "audit"}, "pci": {"group": "*"}};
$scope.switchTab = function (tab) {
$scope.loading = true;
$scope.submenuNavItem = tab;
$scope.checkAlerts($scope._agent.id).then(function (data) { $scope.results = data; $scope.loading = false; }, function() { $scope.results = false; $scope.loading = false; });
let tabGroups = {
"overview": {
"group": "*"
},
"fim": {
"group": "syscheck"
},
"policy_monitoring": {
"group": "rootcheck"
},
"oscap": {
"group": "oscap"
},
"audit": {
"group": "audit"
},
"pci": {
"group": "*"
}
};
//Print Error
var printError = function (error) {
notify.error(error.message);
};
$scope.switchTab = (tab) => {
$scope.loading = true;
$scope.submenuNavItem = tab;
$scope.checkAlerts($scope._agent.id)
.then((data) => {
$scope.results = data;
$scope.loading = false;
})
.catch(() => {
$scope.results = false;
$scope.loading = false;
});
};
//Print Error
const printError = (error) => notify.error(error.message);
// Check if there are any alert.
$scope.checkAlerts = function (agent_id) {
var group = tabGroups[$scope.submenuNavItem].group;
var payload = {};
var fields = {"fields" : [{"field": "rule.groups", "value": group},{"field": "agent.id", "value": agent_id}]};
$scope.checkAlerts = (agent_id) => {
let group = tabGroups[$scope.submenuNavItem].group;
let payload = {};
let fields = {
"fields": [{
"field": "rule.groups",
"value": group
}, {
"field": "agent.id",
"value": agent_id
}]
};
// No filter needed for general/pci
if(group == "*")
fields = {"fields" : [{"field": "agent.id", "value": agent_id}]};
var clusterName = {"cluster" : appState.getClusterInfo().cluster};
var timeInterval = {"timeinterval": {"gte" : $scope.timeGTE, "lt": $scope.timeLT}};
if (group === '*'){
fields = {
"fields": [{
"field": "agent.id",
"value": agent_id
}]
};
}
let clusterName = {
"cluster": appState.getClusterInfo().cluster
};
let timeInterval = {
"timeinterval": {
"gte": $scope.timeGTE,
"lt": $scope.timeLT
}
};
angular.extend(payload, fields, clusterName, timeInterval);
var deferred = $q.defer();
genericReq.request('POST', '/api/wazuh-elastic/alerts-count/', payload).then(function (data) {
if(data.data.data != 0)
let deferred = $q.defer();
genericReq.request('POST', '/api/wazuh-elastic/alerts-count/', payload)
.then((data) => {
if (data.data.data !== 0){
deferred.resolve(true);
else
} else {
deferred.resolve(false);
}
});
return deferred.promise;
};
$scope.getAgentStatusClass = function (agentStatus) {
agentStatus == "Active" ? "green" : "red";
};
$scope.getAgentStatusClass = (agentStatus) => agentStatus === "Active" ? "green" : "red";
$scope.formatAgentStatus = function (agentStatus) {
if (agentStatus != "Active" || agentStatus == "Disconnected")
return "Never connected";
else return agentStatus;
};
$scope.formatAgentStatus = (agentStatus) => {
let condition = (agentStatus !== "Active" || agentStatus === "Disconnected");
return (condition) ? "Never connected" : agentStatus;
};
$scope.extensionStatus = function (extension) {
return appState.getExtensions().extensions[extension];
};
$scope.extensionStatus = (extension) => appState.getExtensions().extensions[extension];
$scope.applyAgent = function (agent) {
if (agent) {
$scope.loading = true;
$scope.applyAgent = (agent) => {
if (agent) {
$scope.loading = true;
$scope.submenuNavItem = 'overview';
$scope.agentInfo = {};
$scope.agentInfo = {};
// Get Agent Info
apiReq.request('GET', '/agents/' + agent.id, {}).then(function (data) {
console.log(data);
apiReq.request('GET', `/agents/${agent.id}`, {})
.then((data) => {
$scope.agentInfo = data.data.data;
$rootScope.agent = $scope.agentInfo;
if(angular.isUndefined($scope.agentInfo.version))
if (typeof $scope.agentInfo.version === 'undefined'){
$scope.agentInfo.version = "Unknown";
if(angular.isUndefined($scope.agentInfo.os)) {
$scope.agentOs = "Unknown";
}
else {
if(!angular.isUndefined($scope.agentInfo.os.name)) {
$scope.agentOs = $scope.agentInfo.os.name + ' ' + $scope.agentInfo.os.version;
}
else {
if(!angular.isUndefined($scope.agentInfo.os.uname)){
if (typeof $scope.agentInfo.os === 'undefined') {
$scope.agentOs = "Unknown";
} else {
if (typeof $scope.agentInfo.os.name !== 'undefined') {
$scope.agentOs = `${$scope.agentInfo.os.name} ${$scope.agentInfo.os.version}`;
} else {
if (typeof $scope.agentInfo.os.uname !== 'undefined') {
$scope.agentOs = $scope.agentInfo.os.uname;
}
else {
} else {
$scope.agentOs = "Unknown";
}
}
}
if(angular.isUndefined($scope.agentInfo.lastKeepAlive))
if (typeof $scope.agentInfo.lastKeepAlive === 'undefined'){
$scope.agentInfo.lastKeepAlive = "Unknown";
}
$scope._agent = data.data.data;
$scope.search = data.data.data.name;
$location.search('id', $scope._agent.id);
$scope.checkAlerts($scope._agent.id).then(function (data) {
$scope.checkAlerts($scope._agent.id)
.then((data) => {
$scope.results = data;
$scope.loading = false;
});
apiReq.request('GET', '/syscheck/' + agent.id + '/last_scan', {}).then(function (data) {
$scope.agentInfo.syscheck = data.data.data;
apiReq.request('GET', `/syscheck/${agent.id}/last_scan`, {})
.then((data) => {
$scope.agentInfo.syscheck = data.data.data;
$scope.agentInfo.syscheck.duration = "Unknown";
if($scope.agentInfo.syscheck.end != null && $scope.agentInfo.syscheck.start != null) {
var syscheckTime = new Date($scope.agentInfo.syscheck.start);
var syscheckEndTime = new Date($scope.agentInfo.syscheck.end);
var minutes = ((syscheckEndTime-syscheckTime)/1000)/60;
if (!$scope.agentInfo.syscheck.end && !$scope.agentInfo.syscheck.start) {
let syscheckTime = new Date($scope.agentInfo.syscheck.start);
let syscheckEndTime = new Date($scope.agentInfo.syscheck.end);
let minutes = ((syscheckEndTime - syscheckTime) / 1000) / 60;
$scope.agentInfo.syscheck.duration = window.Math.round(minutes);
}else if($scope.agentInfo.syscheck.end == null) {
} else if (!$scope.agentInfo.syscheck.end) {
$scope.agentInfo.syscheck.end = "Unknown";
}else {
} else {
$scope.agentInfo.syscheck.start = "Unknown";
}
}, printError);
})
.catch((err) => printError(err));
// Get rootcheck info
apiReq.request('GET', '/rootcheck/' + agent.id + '/last_scan', {}).then(function (data) {
$scope.agentInfo.rootcheck = data.data.data;
apiReq.request('GET', `/rootcheck/${agent.id}/last_scan`, {})
.then((data) => {
$scope.agentInfo.rootcheck = data.data.data;
$scope.agentInfo.rootcheck.duration = "Unknown";
if($scope.agentInfo.rootcheck.end != null && $scope.agentInfo.rootcheck.start != null) {
var rootcheckTime = new Date($scope.agentInfo.rootcheck.start);
var rootcheckEndTime = new Date($scope.agentInfo.rootcheck.end);
var minutes = ((rootcheckEndTime-rootcheckTime)/1000)/60;
if ($scope.agentInfo.rootcheck.end && $scope.agentInfo.rootcheck.start) {
let rootcheckTime = new Date($scope.agentInfo.rootcheck.start);
let rootcheckEndTime = new Date($scope.agentInfo.rootcheck.end);
let minutes = ((rootcheckEndTime - rootcheckTime) / 1000) / 60;
$scope.agentInfo.rootcheck.duration = window.Math.round(minutes);
}else if($scope.agentInfo.rootcheck.end == null) {
} else if ($scope.agentInfo.rootcheck.end) {
$scope.agentInfo.rootcheck.end = "Unknown";
}else {
} else {
$scope.agentInfo.rootcheck.start = "Unknown";
}
}, printError);
}, printError);
}
};
})
.catch((err) => printError(err));
})
.catch((err) => printError(err));
}
};
// Copy agent from groups tab
if($rootScope.comeFromGroups){
let tmpAgent = Object.assign($rootScope.comeFromGroups);
delete $rootScope.comeFromGroups;
$scope.applyAgent(tmpAgent);
}
// Watchers
$scope.$watch('tabView', function() {
$location.search('tabView', $scope.tabView);
});
$scope.$watch('tabView', () => $location.search('tabView', $scope.tabView));
// Watch for timefilter changes
$scope.$on('$routeUpdate', function() {
if($location.search()._g && $location.search()._g != "()") {
var currentTimeFilter = rison.decode($location.search()._g);
$scope.$on('$routeUpdate', () => {
if ($location.search()._g && $location.search()._g !== '()') {
let currentTimeFilter = rison.decode($location.search()._g);
// Check if timefilter has changed and update values
var gParameter;
if($route.current.params._g.startsWith("h@")) {
let gParameter;
if ($route.current.params._g.startsWith("h@")) {
gParameter = sessionStorage.getItem($route.current.params._g);
}else {
} else {
gParameter = $route.current.params._g;
}
if(gParameter != "()" && ($scope.timeGTE != currentTimeFilter.time.from || $scope.timeLT != currentTimeFilter.time.to)) {
if (gParameter != "()" && (
$scope.timeGTE != currentTimeFilter.time.from ||
$scope.timeLT != currentTimeFilter.time.to)
) {
$scope.timeGTE = currentTimeFilter.time.from;
$scope.timeLT = currentTimeFilter.time.to;
$scope.timeLT = currentTimeFilter.time.to;
//Check for present data for the selected tab
if($scope.submenuNavItem != "preview") {
$scope.checkAlerts($scope._agent.id).then(function (data) { $scope.results = data; }, function() { $scope.results = false; });
if ($scope.submenuNavItem !== "preview") {
if(!('_agent' in $scope)){
console.log('Waiting for an agent...');
} else {
$scope.checkAlerts($scope._agent.id)
.then((data) => $scope.results = data)
.catch(() => $scope.results = false);
}
}
}
}
// Check if tab is empty, then reset to preview
if(angular.isUndefined($location.search().tab) && angular.isUndefined($location.search().id)) {
if (typeof $location.search().tab === 'undefined' &&
typeof $location.search().id === 'undefined') {
$scope.submenuNavItem = "preview";
delete $scope._agent;
$scope.search = "";
}
});
//Load
try {
$scope.agentsAutoComplete.nextPage('').then(function (data) {
$scope.loading = false;
});
} catch (e) {
notify.error('Unexpected exception loading controller');
}
//Load
try {
$scope.agentsAutoComplete.nextPage('')
.then(() => $scope.loading = false);
} catch (e) {
notify.error('Unexpected exception loading controller');
}
//Destroy
$scope.$on("$destroy", () => $scope.agentsAutoComplete.reset());
//Destroy
$scope.$on("$destroy", function () {
$scope.agentsAutoComplete.reset();
});
});
app.controller('agentsOverviewController', function ($scope) {
});
app.controller('agentsOverviewController', function ($scope) {});
app.controller('fimController', function ($scope) {
$scope._fimEvent = 'all'
});
app.controller('fimController', ($scope) => $scope._fimEvent = 'all');
app.controller('pmController', function ($scope) {
});
app.controller('pmController', function ($scope) {});
app.controller('auditController', function ($scope) {
});
app.controller('auditController', function ($scope) {});
app.controller('oscapController', function ($scope) {
});
app.controller('oscapController', function ($scope) {});
app.controller('PCIController', function ($scope, genericReq) {
var tabs = [];
genericReq.request('GET', '/api/wazuh-api/pci/all').then(function (data) {
angular.forEach(data.data, function(value, key) {
tabs.push({"title": key, "content": value});
let tabs = [];
genericReq.request('GET', '/api/wazuh-api/pci/all')
.then((data) => {
angular.forEach(data.data, (value, key) => {
tabs.push({
"title": key,
"content": value
});
});
});
});
$scope.tabs = tabs;
$scope.selectedIndex = 0;
$scope.tabs = tabs;
$scope.selectedIndex = 0;
$scope.addTab = function (title, view) {
view = view || title + " Content View";
tabs.push({ title: title, content: view, disabled: false});
};
$scope.removeTab = function (tab) {
var index = tabs.indexOf(tab);
tabs.splice(index, 1);
};
});
$scope.addTab = (title, view) => {
view = view || title + " Content View";
tabs.push({
title: title,
content: view,
disabled: false
});
};
$scope.removeTab = (tab) => {
let index = tabs.indexOf(tab);
tabs.splice(index, 1);
};
});

View File

@ -1,74 +1,92 @@
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
// We are using the DataHandler template and customize its path to get information about agents
app.factory('Agents', function(DataHandler) {
var Agents = new DataHandler();
Agents.path = '/agents';
return Agents;
app.factory('Agents', function (DataHandler) {
let Agents = new DataHandler();
Agents.path = '/agents';
return Agents;
});
app.controller('agentsPreviewController', function ($scope, Notifier, genericReq, apiReq, appState, Agents) {
const notify = new Notifier({location: 'Agents - Preview'});
$scope.loading = true;
$scope.agents = Agents;
$scope.status = 'all';
$scope.osPlatform = 'all';
$scope.osPlatforms = []
$scope.mostActiveAgent = {"name" : "", "id" : ""};
//Print Error
var printError = function (error) {
notify.error(error.message);
const notify = new Notifier({ location: 'Agents - Preview' });
$scope.loading = true;
$scope.agents = Agents;
$scope.status = 'all';
$scope.osPlatform = 'all';
$scope.osPlatforms = [];
$scope.mostActiveAgent = {
"name": "",
"id": ""
};
var load = function () {
$scope.agents.nextPage('').then(function (data) {
// Retrieve os list
angular.forEach($scope.agents.items, function(agent) {
$scope.osPlatforms.push(agent.os.name);
});
$scope.osPlatforms = new Set($scope.osPlatforms);
$scope.osPlatforms = Array.from($scope.osPlatforms); // Angularjs doesn't support ES6 objects
});
//Print Error
const printError = (error) => notify.error(error.message);
// Get last agent !!!!!!!
const load = () => {
$scope.agents.nextPage('')
.then(() => {
// Retrieve os list
for(let agent of $scope.agents.items){
if('os' in agent && 'name' in agent.os){
let exists = $scope.osPlatforms.filter((e) => e.name === agent.os.name &&
e.platform === agent.os.platform &&
e.version === agent.os.version);
if(!exists.length){
$scope.osPlatforms.push({
name: agent.os.name,
platform: agent.os.platform,
version: agent.os.version
});
}
}
}
});
genericReq.request('GET', '/api/wazuh-elastic/top/' + appState.getClusterInfo().cluster + '/agent.name').then(function (data) {
if(data.data.data == "") {
$scope.mostActiveAgent.name = $scope.cluster_info.manager;
$scope.mostActiveAgent.id = "000";
return;
}
$scope.mostActiveAgent.name = data.data.data;
genericReq.request('GET', '/api/wazuh-elastic/top/' + appState.getClusterInfo().cluster + '/agent.id').then(function (data) {
if(data.data.data == "" && $scope.mostActiveAgent.name != "") {
$scope.mostActiveAgent.id = "000";
}else{
$scope.mostActiveAgent.id = data.data.data;
}
$scope.loading = false;
}, printError);
}, printError);
apiReq.request('GET', '/agents/summary', {}).then(function (data) {
$scope.agentsCountActive = data.data.data.Active;
$scope.agentsCountDisconnected = data.data.data.Disconnected;
$scope.agentsCountNeverConnected = data.data.data['Never connected'];
$scope.agentsCountTotal = data.data.data.Total;
$scope.agentsCoverity = (data.data.data.Active / data.data.data.Total) * 100;
$scope.loading = false;
}, printError);
// Get last agent !!!!!!!
let tmpUrl = `/api/wazuh-elastic/top/${appState.getClusterInfo().cluster}/agent.name`;
let tmpUrl2 = `/api/wazuh-elastic/top/${appState.getClusterInfo().cluster}/agent.id`;
genericReq.request('GET', tmpUrl)
.then((data) => {
if (data.data.data === '') {
$scope.mostActiveAgent.name = $scope.cluster_info.manager;
$scope.mostActiveAgent.id = '000';
return;
}
$scope.mostActiveAgent.name = data.data.data;
genericReq.request('GET', tmpUrl2)
.then((data) => {
if (data.data.data === '' && $scope.mostActiveAgent.name !== '') {
$scope.mostActiveAgent.id = '000';
} else {
$scope.mostActiveAgent.id = data.data.data;
}
$scope.loading = false;
})
.catch((error) => printError(error));
})
.catch((error) => printError(error));
apiReq.request('GET', '/agents/summary', {})
.then((data) => {
$scope.agentsCountActive = data.data.data.Active;
$scope.agentsCountDisconnected = data.data.data.Disconnected;
$scope.agentsCountNeverConnected = data.data.data['Never connected'];
$scope.agentsCountTotal = data.data.data.Total;
$scope.agentsCoverity = (data.data.data.Active / data.data.data.Total) * 100;
$scope.loading = false;
})
.catch((error) => printError(error));
};
//Load
try {
load();
} catch (e) {
notify.error("Unexpected exception loading controller");
notify.error("Unexpected exception loading controller");
}
//Destroy
$scope.$on("$destroy", function () {
$scope.agents.reset();
});
});
$scope.$on("$destroy", () => $scope.agents.reset());
});

View File

@ -1,5 +1,5 @@
// Require config
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
import chrome from 'ui/chrome';
app.controller('dashboardController', function ($scope, $location) {

View File

@ -1,95 +1,115 @@
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
// We are using the DataHandler template and customize its path to get information about groups
app.factory('Groups', function(DataHandler) {
var Groups = new DataHandler();
Groups.path = '/agents/groups';
return Groups;
app.factory('Groups', function (DataHandler) {
let Groups = new DataHandler();
Groups.path = '/agents/groups';
return Groups;
});
app.factory('GroupAgents', function(DataHandler) {
var GroupAgents = new DataHandler();
return GroupAgents;
app.factory('GroupAgents', function (DataHandler) {
return new DataHandler();
});
app.factory('GroupFiles', function(DataHandler) {
var GroupFiles = new DataHandler();
return GroupFiles;
app.factory('GroupFiles', function (DataHandler) {
return new DataHandler();
});
app.filter('prettyJSON', function () {
return function(json) { return angular.toJson(json, true); };
});
// Groups preview controller
app.controller('groupsPreviewController', function($scope, apiReq, Groups, GroupFiles, GroupAgents) {
$scope.searchTerm = '';
$scope.load = true;
app.controller('groupsPreviewController',
function ($scope, $timeout, $rootScope,$mdSidenav, $location, apiReq, Groups, GroupFiles, GroupAgents) {
$scope.searchTerm = '';
$scope.searchTermAgent = '';
$scope.searchTermFile = '';
$scope.load = true;
$scope.groups = Groups;
$scope.groupAgents = GroupAgents;
$scope.groupFiles = GroupFiles;
$scope.groups = Groups;
$scope.groupAgents = GroupAgents;
$scope.groupFiles = GroupFiles;
// Actual execution in the controller's initialization
$scope.groups.nextPage('')
.then(() => $scope.loadGroup(0));
// Actual execution in the controller's initialization
$scope.groups.nextPage('').then (function (data) {
$scope.loadGroup(0);
});
$scope.load = false;
$scope.load = false;
$scope.showFiles = (index) => {
$scope.fileViewer = false;
$scope.groupFiles.reset();
$scope.groupFiles.path = `/agents/groups/${$scope.groups.items[index].name}/files`;
$scope.groupFiles.nextPage('');
};
$scope.showFiles = function (index) {
$scope.groupFiles.reset();
$scope.groupFiles.path = '/agents/groups/' + $scope.groups.items[index].name + "/files";
$scope.groupFiles.nextPage('');
}
$scope.showAgents = (index) => {
$scope.fileViewer = false;
$scope.groupAgents.reset();
$scope.groupAgents.path = `/agents/groups/${$scope.groups.items[index].name}`;
$scope.groupAgents.nextPage('');
};
$scope.showAgents = function (index) {
$scope.groupAgents.reset();
$scope.groupAgents.path = '/agents/groups/' + $scope.groups.items[index].name;
$scope.groupAgents.nextPage('').then(function (data) {
angular.forEach($scope.groupAgents.items, function(agent) {
apiReq.request('GET', "/agents/" + agent.id, {}).then (function (data) {
console.log(data);
$scope.showAgent = (agent) => {
$rootScope.comeFromGroups = agent;
$location.path('/agents');
};
$scope.loadGroup = (index) => {
$scope.fileViewer = false;
$scope.groupAgents.reset();
$scope.groupFiles.reset();
$scope.selectedGroup = index;
$scope.showFiles(index);
$scope.showAgents(index);
};
// Select specific group
$scope.checkSelected = (index) => {
for(let group of $scope.groups.items){
if (group.selected) {
group = false;
}
}
$scope.groups.items[index] = true;
};
$scope.showFile = (index) => {
let filename = $scope.groupFiles.items[index].filename;
if(filename === '../ar.conf') filename = 'ar.conf';
$scope.fileViewer = true;
$scope.file = 'Loading...';
let tmpName = `/agents/groups/${$scope.groups.items[$scope.selectedGroup].name}`+
`/files/${filename}`;
apiReq.request('GET', tmpName, {})
.then((data) => $scope.file = data.data.data)
.catch((err) => $scope.file = {
group: $scope.groups.items[$scope.selectedGroup].name,
file: $scope.groupFiles.items[index].filename,
error: err.message || err
});
});
};
// Changing the view to overview a specific group
$scope.groupOverview = (group) => {
$scope.$parent.$parent.groupName = group;
$scope.$parent.$parent.groupsMenu = 'overview';
};
// Resetting the factory configuration
$scope.$on("$destroy", () => {
$scope.groups.reset();
$scope.groupFiles.reset();
$scope.groupAgents.reset();
});
}
$scope.loadGroup = function (index) {
$scope.groupAgents.reset();
$scope.groupFiles.reset();
$scope.selectedGroup = index;
$scope.showFiles(index);
$scope.showAgents(index);
}
// Select specific group
$scope.checkSelected = function(index ) {
angular.forEach($scope.groups.items, function(group) {
if (group.selected) group = false;
});
$scope.groups.items[index] = true;
}
$scope.showFile = function(index) {
$scope.test = !$scope.test;
$scope.file = 'Loading...';
apiReq.request('GET', "/agents/groups/" + $scope.groups.items[$scope.selectedGroup].name + "/files/" + $scope.groupFiles.items[index].filename, {}).then (function (data) {
$scope.file=data.data;
});
}
// Changing the view to overview a specific group
$scope.groupOverview = function(group) {
$scope.$parent.$parent.groupName = group;
$scope.$parent.$parent.groupsMenu = "overview";
}
// Resetting the factory configuration
$scope.$on("$destroy", function(){
$scope.groups.reset();
$scope.groupsFiles.reset();
$scope.groupsAgents.reset();
});
});
app.controller('groupsController', function ($scope) {
$scope.groupsMenu = "preview";
$scope.groupName = '';
});
$scope.groupsMenu = 'preview';
$scope.groupName = '';
});

View File

@ -1,70 +1,80 @@
// Require config
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
app.controller('managerController', function ($scope, $routeParams, $location) {
$scope.submenuNavItem = "status";
$scope.submenuNavItem2 = "rules";
$scope.submenuNavItem = 'status';
$scope.submenuNavItem2 = 'rules';
if($routeParams.tab)
$scope.submenuNavItem = $routeParams.tab;
// Watchers
$scope.$watch('submenuNavItem', function() {
$location.search('tab', $scope.submenuNavItem);
});
$scope.setRulesTab = function(tab) {
$scope.submenuNavItem2 = tab;
};
if ($routeParams.tab){
$scope.submenuNavItem = $routeParams.tab;
}
// Watchers
$scope.$watch('submenuNavItem', () => $location.search('tab', $scope.submenuNavItem));
$scope.setRulesTab = (tab) => $scope.submenuNavItem2 = tab;
});
app.controller('managerStatusController', function ($scope, Notifier, apiReq) {
//Initialization
const notify = new Notifier({ location: 'Manager - Status' });
$scope.load = true;
$scope.load = true;
//Print Error
var printError = function (error) {
notify.error(error.message);
};
const printError = (error) => notify.error(error.message);
//Functions
$scope.getDaemonStatusClass = function (daemonStatus) {
if (daemonStatus == "running")
return "status green"
else
return "status red";
$scope.getDaemonStatusClass = (daemonStatus) => {
return (daemonStatus === 'running') ? 'status green' : 'status red';
};
var load = function () {
apiReq.request('GET', '/agents/summary', {}).then(function (data) {
$scope.agentsCountActive = data.data.data.Active;
$scope.agentsCountDisconnected = data.data.data.Disconnected;
const load = () => {
apiReq
.request('GET', '/agents/summary', {})
.then((data) => {
$scope.agentsCountActive = data.data.data.Active;
$scope.agentsCountDisconnected = data.data.data.Disconnected;
$scope.agentsCountNeverConnected = data.data.data['Never connected'];
$scope.agentsCountTotal = data.data.data.Total;
$scope.agentsCoverity = (data.data.data.Active / data.data.data.Total) * 100;
}, printError);
$scope.agentsCountTotal = data.data.data.Total;
$scope.agentsCoverity = (data.data.data.Active / data.data.data.Total) * 100;
})
.catch((error) => printError(error));
apiReq.request('GET', '/manager/status', {}).then(function (data) {
$scope.daemons = data.data.data;
}, printError);
apiReq
.request('GET', '/manager/status', {})
.then((data) => $scope.daemons = data.data.data)
.catch((error) => printError(error));
apiReq.request('GET', '/manager/info', {}).then(function (data) {
apiReq
.request('GET', '/manager/info', {})
.then((data) => {
$scope.managerInfo = data.data.data;
apiReq.request('GET', '/rules', { offset: 0, limit: 1 }).then(function (data) {
$scope.totalRules = data.data.data.totalItems;
apiReq.request('GET', '/decoders', { offset: 0, limit: 1 }).then(function (data) {
$scope.totalDecoders = data.data.data.totalItems;
$scope.load = false;
}, printError);
}, printError);
}, printError);
return apiReq.request('GET', '/rules', {
offset: 0,
limit: 1
});
})
.then((data) => {
$scope.totalRules = data.data.data.totalItems;
return apiReq.request('GET', '/decoders', {
offset: 0,
limit: 1
});
})
.then((data) => {
$scope.totalDecoders = data.data.data.totalItems;
$scope.load = false;
})
.catch((error) => printError(error));
apiReq.request('GET', '/agents', { offset: 0, limit: 1, sort: '-id' }).then(function (data) {
apiReq.request('GET', '/agents/' + data.data.data.items[0].id, {}).then(function (data) {
$scope.agentInfo = data.data.data;
}, printError);
}, printError);
apiReq.request('GET', '/agents', {
offset: 0,
limit: 1,
sort: '-id'
})
.then((data) => apiReq.request('GET', `/agents/${data.data.data.items[0].id}`, {}))
.then((data) => $scope.agentInfo = data.data.data)
.catch((error) => printError(error));
};
//Load
@ -77,30 +87,32 @@ app.controller('managerStatusController', function ($scope, Notifier, apiReq) {
app.controller('managerConfigurationController', function ($scope, Notifier, apiReq) {
//Initialization
const notify = new Notifier({ location: 'Manager - Configuration' });
$scope.load = true;
$scope.isArray = angular.isArray;
const notify = new Notifier({ location: 'Manager - Configuration' });
$scope.load = true;
$scope.isArray = angular.isArray;
//Print Error
var printError = function (error) {
notify.error(error.message);
};
const printError = (error) => notify.error(error.message);
//Functions
var load = function () {
apiReq.request('GET', '/manager/status', {}).then(function (data) {
const load = () => {
apiReq
.request('GET', '/manager/status', {})
.then((data) => {
$scope.daemons = data.data.data;
apiReq.request('GET', '/manager/configuration', {}).then(function (data) {
$scope.managerConfiguration = data.data.data;
$scope.load = false;
}, printError);
}, printError);
return apiReq.request('GET', '/manager/configuration', {});
})
.then((data) => {
$scope.managerConfiguration = data.data.data;
$scope.load = false;
})
.catch((error) => printError(error));
};
//Load
try {
load();
} catch (e) {
notify.error("Unexpected exception loading controller");
notify.error("Unexpected exception loading controller");
}
});
});

View File

@ -1,27 +1,25 @@
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
// We are using the DataHandler template and customize its path to get information about logs
app.factory('Logs', function(DataHandler) {
var Logs = new DataHandler();
Logs.path = '/manager/logs';
return Logs;
app.factory('Logs', function (DataHandler) {
let Logs = new DataHandler();
Logs.path = '/manager/logs';
return Logs;
});
// Logs controller
app.controller('managerLogController', function($scope, Logs, apiReq) {
$scope.searchTerm = '';
var requests = 2;
var servedRequests = 0;
$scope.loading = true;
$scope.logs = Logs;
$scope.logs.nextPage('').then(function (data) { servedRequests++; if(servedRequests == requests) $scope.loading = false;});
apiReq.request('GET', '/manager/logs/summary', {}).then(function (data) {
$scope.summary = data.data.data;
servedRequests++; if(servedRequests == requests) $scope.loading = false;
});
app.controller('managerLogController', function ($scope, Logs, apiReq) {
$scope.searchTerm = '';
$scope.loading = true;
$scope.logs = Logs;
// Resetting the factory configuration
$scope.$on("$destroy", function(){
$scope.logs.reset();
});
});
$scope.logs.nextPage('')
.then(() => apiReq.request('GET', '/manager/logs/summary', {}))
.then(data => {
$scope.summary = data.data.data;
$scope.loading = false;
});
// Resetting the factory configuration
$scope.$on("$destroy", () => $scope.logs.reset());
});

View File

@ -1,80 +1,144 @@
import rison from 'rison-node';
var app = require('ui/modules').get('app/wazuh', []).controller('overviewController', function ($scope, $q, $routeParams, $route, $location, $rootScope, appState, genericReq) {
let app = require('ui/modules')
.get('app/wazuh', [])
.controller('overviewController',
function ($scope, $q, $routeParams, $route, $location, $rootScope, appState, genericReq) {
$rootScope.page = "overview";
$scope.submenuNavItem = "general";
$scope.extensions = appState.getExtensions().extensions;
$rootScope.page = 'overview';
$scope.submenuNavItem = 'general';
$scope.extensions = appState.getExtensions().extensions;
if ($location.search().tabView)
if ($location.search().tabView){
$scope.tabView = $location.search().tabView;
else {
$scope.tabView = "panels";
$location.search("tabView", "panels");
} else {
$scope.tabView = 'panels';
$location.search('tabView', 'panels');
}
$scope.timeGTE = "now-1d";
$scope.timeLT = "now";
$scope.timeGTE = 'now-1d';
$scope.timeLT = 'now';
// Object for matching nav items and Wazuh groups
var tabGroups = { "general": {"group": "*"}, "fim": {"group": "syscheck"}, "pm": {"group": "rootcheck"}, "oscap": {"group": "oscap"}, "audit": {"group": "audit"}, "pci": {"group": "*"} };
let tabGroups = {
"general": {
"group": "*"
},
"fim": {
"group": "syscheck"
},
"pm": {
"group": "rootcheck"
},
"oscap": {
"group": "oscap"
},
"audit": {
"group": "audit"
},
"pci": {
"group": "*"
}
};
$scope.hideRing = function(items) {
console.log("hidering is getting called");
if($(".vis-editor-content" ).length >= items)
return true;
return false;
}
$scope.hideRing = (items) => {
//console.log("hidering is getting called");
return $(".vis-editor-content").length >= items;
};
// Switch tab
$scope.switchTab = function (tab) {
$scope.loading = true;
$scope.switchTab = (tab) => {
$scope.loading = true;
$scope.submenuNavItem = tab;
$scope.checkAlerts().then(function (data) { $scope.results = data; $scope.loading = false; }, function(){ $scope.results = false; $scope.loading = false; });
$scope.checkAlerts()
.then((data) => {
$scope.results = data;
$scope.loading = false;
})
.catch(() => {
$scope.results = false;
$scope.loading = false;
});
};
// Check if there are alerts.
$scope.checkAlerts = function () {
var group = tabGroups[$scope.submenuNavItem].group;
var payload = {};
var fields = {"fields" : [{"field": "rule.groups", "value": group}]};
$scope.checkAlerts = () => {
let group = tabGroups[$scope.submenuNavItem].group;
let payload = {};
let fields = {
"fields": [{
"field": "rule.groups",
"value": group
}]
};
// No filter needed for general/pci
if(group == "*")
fields = {"fields" : []};
var clusterName = {"cluster" : appState.getClusterInfo().cluster};
var timeInterval = {"timeinterval": {"gte" : $scope.timeGTE, "lt": $scope.timeLT}};
if (group === '*'){
fields = {
"fields": []
};
}
let clusterName = {
"cluster": appState.getClusterInfo().cluster
};
let timeInterval = {
"timeinterval": {
"gte": $scope.timeGTE,
"lt": $scope.timeLT
}
};
angular.extend(payload, fields, clusterName, timeInterval);
var deferred = $q.defer();
genericReq.request('POST', '/api/wazuh-elastic/alerts-count/', payload).then(function (data) {
if(data.data.data != 0)
deferred.resolve(true);
else
deferred.resolve(false);
});
let deferred = $q.defer();
genericReq
.request('POST', '/api/wazuh-elastic/alerts-count/', payload)
.then((data) => {
if (data.data.data !== 0){
deferred.resolve(true);
} else {
deferred.resolve(false);
}
});
return deferred.promise;
};
// Watch for timefilter changes
$scope.$on('$routeUpdate', function() {
if($location.search()._g && $location.search()._g != "()") {
var currentTimeFilter = rison.decode($location.search()._g);
$scope.$on('$routeUpdate', () => {
if ($location.search()._g && $location.search()._g !== '()') {
let currentTimeFilter = rison.decode($location.search()._g);
// Check if timefilter has changed and update values
if(currentTimeFilter.time && ($scope.timeGTE != currentTimeFilter.time.from || $scope.timeLT != currentTimeFilter.time.to)) {
if (currentTimeFilter.time &&
($scope.timeGTE != currentTimeFilter.time.from ||
$scope.timeLT != currentTimeFilter.time.to)) {
$scope.timeGTE = currentTimeFilter.time.from;
$scope.timeLT = currentTimeFilter.time.to;
$scope.checkAlerts().then(function (data) {$scope.results = data;}, function(){ $scope.results = false;});
$scope.timeLT = currentTimeFilter.time.to;
$scope.checkAlerts()
.then((data) => $scope.results = data)
.catch(() => $scope.results = false);
}
}
});
// Watchers
$scope.$watch('tabView', function() {
$location.search('tabView', $scope.tabView);
});
$scope.$watch('tabView', () => $location.search('tabView', $scope.tabView));
// Check alerts
$scope.checkAlerts().then(function (data) {$scope.results = data; $scope.loading = false;}, function(){ $scope.results = false; $scope.loading = false;});
$scope.checkAlerts()
.then((data) => {
$scope.results = data;
$scope.loading = false;
})
.catch(() => {
$scope.results = false;
$scope.loading = false;
});
});
app.controller('overviewGeneralController', function ($scope, appState) {
@ -86,28 +150,33 @@ app.controller('overviewFimController', function ($scope, appState) {
});
app.controller('overviewPMController', function ($scope, appState) {
appState.setOverviewState('pm');
appState.setOverviewState('pm');
});
app.controller('overviewOSCAPController', function ($scope, appState) {
appState.setOverviewState('oscap');
appState.setOverviewState('oscap');
});
app.controller('overviewAuditController', function ($scope, appState) {
appState.setOverviewState('audit');
appState.setOverviewState('audit');
});
app.controller('overviewPCIController', function ($scope, genericReq, appState) {
appState.setOverviewState('pci');
appState.setOverviewState('pci');
var tabs = [];
genericReq.request('GET', '/api/wazuh-api/pci/all').then(function (data) {
angular.forEach(data.data, function(value, key) {
tabs.push({"title": key, "content": value});
let tabs = [];
genericReq
.request('GET', '/api/wazuh-api/pci/all')
.then((data) => {
angular.forEach(data.data, (value, key) => {
tabs.push({
"title": key,
"content": value
});
});
});
});
$scope.tabs = tabs;
$scope.selectedIndex = 0;
$scope.tabs = tabs;
$scope.selectedIndex = 0;
});

View File

@ -1,105 +1,132 @@
var app = require('ui/modules').get('app/wazuh');
var app = require('ui/modules').get('app/wazuh');
// We are using the DataHandler template and customize its path to get information
app.factory('Rules', function(DataHandler) {
var Rules = new DataHandler();
Rules.path = '/rules';
return Rules;
app.factory('Rules', function (DataHandler) {
var Rules = new DataHandler();
Rules.path = '/rules';
return Rules;
});
app.factory('Decoders', function(DataHandler) {
var Decoders = new DataHandler();
Decoders.path = '/decoders';
return Decoders;
app.factory('Decoders', function (DataHandler) {
var Decoders = new DataHandler();
Decoders.path = '/decoders';
return Decoders;
});
app.controller('rulesController', function ($scope, Notifier, Rules) {
//Initialization
const notify = new Notifier({location: 'Manager - Rules'});
const notify = new Notifier({ location: 'Manager - Rules' });
$scope.loading = true;
$scope.rules = Rules;
$scope.setRulesTab('rules');
$scope.rules = Rules;
$scope.setRulesTab('rules');
$scope.analizeRules = function (search) {
$scope.analizeRules = (search) => {
$scope.autoComplete = [];
if (search != '') $scope.autoComplete.push({'name': search, 'type': 'search'});
angular.forEach($scope.rules.items, function(element) {
angular.forEach(element.pci, function(pci) {
$scope.autoComplete.push({'name': pci, 'type': 'pci'});
});
angular.forEach(element.groups, function(group) {
$scope.autoComplete.push({'name': group, 'type': 'group'});
});
$scope.autoComplete.push({'name': element.file, 'type': 'file'})
if (search !== '') $scope.autoComplete.push({
name: search,
type: 'search'
});
for(let element of $scope.rules.items){
for(let pci of element.pci){
$scope.autoComplete.push({
name: pci,
type: 'pci'
});
}
for(let group of element.groups){
$scope.autoComplete.push({
name: group,
type: 'group'
});
}
$scope.autoComplete.push({
name: element.file,
type: 'file'
});
}
$scope.autoComplete = new Set($scope.autoComplete.map(e => JSON.stringify(e)));
$scope.autoComplete = Array.from($scope.autoComplete).map(e => JSON.parse(e));
};
//Load
try {
$scope.rules.nextPage('').then(function (data) { $scope.loading = false; $scope.analizeRules(''); });
$scope.rules.nextPage('')
.then(() => {
$scope.loading = false;
$scope.analizeRules('');
});
} catch (e) {
notify.error("Unexpected exception loading controller");
notify.error('Unexpected exception loading controller');
}
//Destroy
$scope.$on("$destroy", function () {
$scope.rules.reset();
});
$scope.$on('$destroy', () => $scope.rules.reset());
});
app.controller('decodersController', function ($scope, $sce, Notifier, Decoders) {
//Initialization
const notify = new Notifier({location: 'Manager - Decoders'});
$scope.loading = true;
const notify = new Notifier({ location: 'Manager - Decoders' });
$scope.loading = true;
$scope.decoders = Decoders;
$scope.setRulesTab('decoders');
$scope.setRulesTab('decoders');
$scope.analizeDecoders = function (search) {
$scope.analizeDecoders = (search) => {
$scope.autoComplete = [];
if (search != '') $scope.autoComplete.push({'name': search, 'type': 'search'});
angular.forEach($scope.decoders.items, function(element) {
$scope.autoComplete.push({'name': element.file, 'type': 'file'})
});
if (search !== '') {
$scope.autoComplete.push({
name: search,
type: 'search'
});
}
for(let element of $scope.decoders.items){
$scope.autoComplete.push({
name: element.file,
type: 'file'
});
}
$scope.autoComplete = new Set($scope.autoComplete.map(e => JSON.stringify(e)));
$scope.autoComplete = Array.from($scope.autoComplete).map(e => JSON.parse(e));
console.log($scope.autoComplete);
};
$scope.colorRegex = function (regex) {
$scope.colorRegex = (regex) => {
regex = regex.toString();
var colors = [
let colors = [
'#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6
'#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2
'#629E51', '#E5AC0E', '#64B0C8', '#E0752D', '#BF1B00', '#0A50A1', '#962D82', '#614D93', //4
'#7EB26D', '#EAB839', '#6ED0E0', '#EF843C', '#E24D42', '#1F78C1', '#BA43A9', '#705DA0', // Normal
'#9AC48A', '#F2C96D', '#65C5DB', '#F9934E', '#EA6460', '#5195CE', '#D683CE', '#806EB7', //5
'#B7DBAB', '#F4D598', '#70DBED', '#F9BA8F', '#F29191', '#82B5D8', '#E5A8E2', '#AEA2E0', //3
'#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7
'#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7
];
var valuesArray = regex.match(/\(((?!<\/span>).)*?\)(?!<\/span>)/gmi);
var coloredString = regex;
for (var i = 0; i < valuesArray.length; i++) {
let valuesArray = regex.match(/\(((?!<\/span>).)*?\)(?!<\/span>)/gmi);
let coloredString = regex;
for (let i = 0, len = valuesArray.length; i < len; i++) {
coloredString = coloredString.replace(/\(((?!<\/span>).)*?\)(?!<\/span>)/mi, '<span style="color: ' + colors[i] + ' ">' + valuesArray[i] + '</span>');
}
return $sce.trustAsHtml(coloredString);
};
$scope.colorOrder = function (order) {
$scope.colorOrder = (order) => {
order = order.toString();
var colors = [
let colors = [
'#3F6833', '#967302', '#2F575E', '#99440A', '#58140C', '#052B51', '#511749', '#3F2B5B', //6
'#508642', '#CCA300', '#447EBC', '#C15C17', '#890F02', '#0A437C', '#6D1F62', '#584477', //2
'#629E51', '#E5AC0E', '#64B0C8', '#E0752D', '#BF1B00', '#0A50A1', '#962D82', '#614D93', //4
'#7EB26D', '#EAB839', '#6ED0E0', '#EF843C', '#E24D42', '#1F78C1', '#BA43A9', '#705DA0', // Normal
'#9AC48A', '#F2C96D', '#65C5DB', '#F9934E', '#EA6460', '#5195CE', '#D683CE', '#806EB7', //5
'#B7DBAB', '#F4D598', '#70DBED', '#F9BA8F', '#F29191', '#82B5D8', '#E5A8E2', '#AEA2E0', //3
'#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7
'#E0F9D7', '#FCEACA', '#CFFAFF', '#F9E2D2', '#FCE2DE', '#BADFF4', '#F9D9F9', '#DEDAF7' //7
];
var valuesArray = order.split(',');
var coloredString = order;
for (var i = 0; i < valuesArray.length; i++) {
let valuesArray = order.split(',');
let coloredString = order;
for (let i = 0, len = valuesArray.length; i < len; i++) {
coloredString = coloredString.replace(valuesArray[i], '<span style="color: ' + colors[i] + ' ">' + valuesArray[i] + '</span>');
}
return $sce.trustAsHtml(coloredString);
@ -107,13 +134,15 @@ app.controller('decodersController', function ($scope, $sce, Notifier, Decoders)
//Load
try {
$scope.decoders.nextPage('').then(function (data) { $scope.loading = false; $scope.analizeDecoders(''); });
$scope.decoders.nextPage('')
.then(() => {
$scope.loading = false;
$scope.analizeDecoders('');
});
} catch (e) {
notify.error("Unexpected exception loading controller");
notify.error('Unexpected exception loading controller');
}
//Destroy
$scope.$on("$destroy", function () {
$scope.decoders.reset();
});
});
$scope.$on("$destroy", () => $scope.decoders.reset());
});

View File

@ -1,219 +1,268 @@
// Require utils
var base64 = require('plugins/wazuh/utils/base64.js');
let base64 = require('plugins/wazuh/utils/base64.js');
import chrome from 'ui/chrome';
// Require App
var app = require('ui/modules').get('app/wazuh', []).controller('settingsController', function ($scope, $rootScope, $http, $routeParams, $location, Notifier, testAPI, appState, genericReq) {
let app = require('ui/modules')
.get('app/wazuh', [])
.controller('settingsController',
function ($scope, $rootScope, $http, $routeParams, $location, Notifier, testAPI, appState, genericReq) {
$rootScope.page = "settings";
// Initialize
const notify = new Notifier({location: 'Settings'});
$scope.formData = {};
$scope.formData.user = "";
const notify = new Notifier({ location: 'Settings' });
$scope.formData = {};
$scope.formData.user = "";
$scope.formData.password = "";
$scope.formData.url = "";
$scope.accept_ssl = true;
$scope.formData.url = "";
$scope.accept_ssl = true;
$scope.editConfiguration = true;
$scope.menuNavItem = 'settings';
$scope.load = true;
$scope.currentDefault = 0;
$scope.extensions = { oscap: true, audit: true, pci: true};
$scope.menuNavItem = 'settings';
$scope.load = true;
$scope.currentDefault = 0;
$scope.extensions = {
oscap: true,
audit: true,
pci: true
};
$scope.addManagerContainer = false;
$scope.submenuNavItem = "api";
// Default tab
$scope.submenuNavItem = "api";
// URL Tab
var tab = "";
if($routeParams.tab)
$scope.submenuNavItem = $routeParams.tab;
if ($routeParams.tab){
$scope.submenuNavItem = $routeParams.tab;
}
// Watch tab change
$scope.$watch('submenuNavItem', function() {
$scope.$watch('submenuNavItem', () => {
$location.search('tab', $scope.submenuNavItem);
});
// Remove API entry
$scope.removeManager = function(item) {
var index = $scope.apiEntries.indexOf(item);
if($scope.apiEntries[index]._source && $scope.apiEntries[index]._source.active == "true" && $scope.apiEntries.length != 1) {
$scope.removeManager = (item) => {
let index = $scope.apiEntries.indexOf(item);
if ($scope.apiEntries[index]._source &&
$scope.apiEntries[index]._source.active === "true" &&
$scope.apiEntries.length !== 1) {
notify.error("Please set another default manager before removing this one");
return;
}
genericReq.request('DELETE', '/api/wazuh-api/apiEntries/' + $scope.apiEntries[index]._id).then(function (data) {
let tmpUrl = `/api/wazuh-api/apiEntries/${$scope.apiEntries[index]._id}`;
genericReq.request('DELETE', tmpUrl)
.then(() => {
$scope.apiEntries.splice(index, 1);
}, function (data, status) {
})
.catch(() => {
notify.error("Could not remove manager");
});
}
};
// Set manager default
$scope.setDefault = function(item) {
var index = $scope.apiEntries.indexOf(item);
genericReq.request('PUT', '/api/wazuh-api/apiEntries/'+$scope.apiEntries[index]._id).then(function (data) {
$scope.setDefault = (item) => {
let index = $scope.apiEntries.indexOf(item);
let tmpUrl = `/api/wazuh-api/apiEntries/${$scope.apiEntries[index]._id}`;
genericReq.request('PUT', tmpUrl)
.then(() => {
appState.setClusterInfo($scope.apiEntries[index]._source.cluster);
$scope.apiEntries[$scope.currentDefault]._source.active = "false";
$scope.apiEntries[index]._source.active = "true";
$scope.apiEntries[$scope.currentDefault]._source.active = 'false';
$scope.apiEntries[index]._source.active = 'true';
$scope.currentDefault = index;
$scope.extensions = $scope.apiEntries[$scope.currentDefault]._source.extensions;
notify.info("Manager "+$scope.apiEntries[index]._source.cluster_info.manager+" set as default");
}, function (data, status) {
notify.info(`Manager ${$scope.apiEntries[index]._source.cluster_info.manager}` +
` set as default`);
})
.catch(() => {
notify.error("Could not set that manager as default");
});
}
};
// Get settings function
$scope.getSettings = function () {
genericReq.request('GET', '/api/wazuh-api/apiEntries').then(function (data, status) {
// Get settings function
$scope.getSettings = () => {
genericReq.request('GET', '/api/wazuh-api/apiEntries')
.then((data) => {
$scope.apiEntries = data.data.length > 0 ? data.data : [];
angular.forEach($scope.apiEntries, function (value, key) {
if(value._source && value._source.active == "true"){
angular.forEach($scope.apiEntries, (value, key) => {
if (value._source && value._source.active === 'true') {
$scope.currentDefault = key;
if(value._source.extensions){
if (value._source.extensions) {
$scope.extensions = value._source.extensions;
}else{
} else {
$scope.extensions.oscap = true;
$scope.extensions.audit = true;
$scope.extensions.pci = true;
$scope.extensions.pci = true;
}
}
});
},function (data, status) {
})
.catch(() => {
notify.error("Error getting API entries");
});
};
};
// Save settings function
$scope.saveSettings = function () {
var activeStatus = "false";
if($scope.apiEntries.length == 0)
activeStatus = "true";
// Save settings function
$scope.saveSettings = () => {
let activeStatus = ($scope.apiEntries.length === 0) ? 'true' : 'false';
var tmpData = { 'user': $scope.formData.user, 'password': base64.encode($scope.formData.password), 'url': $scope.formData.url, 'port': $scope.formData.port, 'cluster_info': {}, 'insecure': "true", 'active': activeStatus, 'id': $scope.apiEntries.length };
let tmpData = {
'user': $scope.formData.user,
'password': base64.encode($scope.formData.password),
'url': $scope.formData.url,
'port': $scope.formData.port,
'cluster_info': {},
'insecure': 'true',
'active': activeStatus,
'id': $scope.apiEntries.length
};
testAPI.check(tmpData).then(function (data) {
// API Check correct. Get Cluster info
tmpData.cluster_info = data.data;
if(activeStatus) {
appState.setClusterInfo(tmpData.cluster_info);
}
testAPI.check(tmpData)
.then((data) => {
// API Check correct. Get Cluster info
tmpData.cluster_info = data.data;
if (activeStatus) {
appState.setClusterInfo(tmpData.cluster_info);
}
tmpData.extensions = {"oscap": true, "audit": true, "pci": true};
tmpData.extensions = {
"oscap": true,
"audit": true,
"pci": true
};
// Insert new API entry
genericReq.request('PUT', '/api/wazuh-api/settings', tmpData).then(function (data) {
var newEntry = {
'_id': data.data.response._id,
_source: {
cluster_info: tmpData.cluster_info,
active: tmpData.active,
url: tmpData.url,
api_user: tmpData.user,
api_port: tmpData.port
}
};
$scope.apiEntries.push(newEntry);
notify.info('Wazuh API successfully added');
$scope.addManagerContainer = false;
$scope.formData.user = "";
$scope.formData.password = "";
$scope.formData.url = "";
$scope.formData.port = "";
// Fetch agents on demand
// Insert new API entry
genericReq.request('PUT', '/api/wazuh-api/settings', tmpData)
.then((data) => {
let newEntry = {
_id: data.data.response._id,
_source: {
cluster_info: tmpData.cluster_info,
active: tmpData.active,
url: tmpData.url,
api_user: tmpData.user,
api_port: tmpData.port
}
};
$scope.apiEntries.push(newEntry);
notify.info('Wazuh API successfully added');
$scope.addManagerContainer = false;
$scope.formData.user = "";
$scope.formData.password = "";
$scope.formData.url = "";
$scope.formData.port = "";
// Fetch agents on demand
genericReq.request('GET', '/api/wazuh-api/fetchAgents').then(function(data){} , function (data, status) {
notify.error("Error fetching agents");
});
}, function (data, status) {
if (status == '400') {
notify.error("Please, fill all the fields in order to connect with Wazuh RESTful API.");
} else {
notify.error("Some error ocurred, could not save data in elasticsearch.");
}
});
}, printError);
};
genericReq.request('GET', '/api/wazuh-api/fetchAgents')
.then(() => {})
.catch(() => {
notify.error("Error fetching agents");
});
})
.catch((error, status) => {
if (status === '400') {
notify.error("Please, fill all the fields in order to connect " +
"with Wazuh RESTful API.");
} else {
notify.error("Some error ocurred, could not save data in elasticsearch.");
}
});
})
.catch((error) => printError(error));
};
// Check manager connectivity
$scope.checkManager = function (item) {
var index = $scope.apiEntries.indexOf(item);
$scope.checkManager = (item) => {
var tmpData = {
'user': $scope.apiEntries[$scope.currentDefault]._source.api_user,
'user': $scope.apiEntries[$scope.currentDefault]._source.api_user,
'password': $scope.apiEntries[$scope.currentDefault]._source.api_password,
'url': $scope.apiEntries[$scope.currentDefault]._source.url,
'port': $scope.apiEntries[$scope.currentDefault]._source.api_port,
'url': $scope.apiEntries[$scope.currentDefault]._source.url,
'port': $scope.apiEntries[$scope.currentDefault]._source.api_port,
'insecure': "true"
};
testAPI.check(tmpData).then(function (data) {
tmpData.cluster_info = data.data;
var index = $scope.apiEntries.indexOf(item);
genericReq.request('PUT', '/api/wazuh-api/updateApiHostname/' + $scope.apiEntries[index]._id, { "cluster_info": tmpData.cluster_info }).then(function (data) {
testAPI.check(tmpData)
.then((data) => {
tmpData.cluster_info = data.data;
let index = $scope.apiEntries.indexOf(item);
let tmpUrl = `/api/wazuh-api/updateApiHostname/${$scope.apiEntries[index]._id}`;
genericReq.request('PUT',tmpUrl , { "cluster_info": tmpData.cluster_info })
.then(() => {
$scope.apiEntries[index]._source.cluster_info = tmpData.cluster_info;
});
notify.info("Connection success");
}, printError);
};
});
notify.info("Connection success");
})
.catch((error) => printError(error));
};
// Process form
$scope.processForm = function () {
// Process form
$scope.processForm = () => {
$scope.messageError = "";
$scope.saveSettings();
};
};
// Toggle extension
$scope.toggleExtension = function(extension,state) {
if(extension == "oscap" || extension == "audit" || extension == "pci"){
genericReq.request('PUT', '/api/wazuh-api/extension/toggle/' + $scope.apiEntries[$scope.currentDefault]._id + '/' + extension + '/' + state).then(function(){},
function (data, status) {
notify.error("Invalid request when toggle extension state.");
});
$scope.toggleExtension = (extension, state) => {
if (['oscap','audit','pci'].includes(extension)) {
let tmpUrl = `/api/wazuh-api/extension/toggle/` +
`${$scope.apiEntries[$scope.currentDefault]._id}/` +
`${extension}/${state}`;
genericReq.request('PUT', tmpUrl)
.then(() => {})
.catch(() => {
notify.error("Invalid request when toggle extension state.");
});
}
};
var printError = function (data) {
var text;
switch (data.data) {
case 'no_elasticsearch':
text = 'Could not connect with elasticsearch in order to retrieve the credentials.';
break;
case 'no_credentials':
text = 'Valid credentials not found in elasticsearch. It seems the credentials were not saved.';
break;
case 'protocol_error':
text = 'Invalid protocol in the API url. Please, specify <b>http://</b> or <b>https://</b>.';
break;
case 'unauthorized':
text = 'Credentials were found, but they are not valid.';
break;
case 'bad_url':
text = 'The given URL does not contain a valid Wazuh RESTful API installation.';
break;
case 'self_signed':
text = 'The request to Wazuh RESTful API was blocked, because it is using a selfsigned SSL certificate. Please, enable <b>"Accept selfsigned SSL"</b> option if you want to connect anyway.';
break;
case 'not_running':
text = 'There are not services running in the given URL.';
break;
default:
text = 'Unexpected error. '+ data.message;
}
notify.error(text);
const printError = (error) => {
let text;
switch (error.data) {
case 'no_elasticsearch':
text = 'Could not connect with elasticsearch in order to retrieve the credentials.';
break;
case 'no_credentials':
text = 'Valid credentials not found in elasticsearch. It seems the credentials ' +
'were not saved.';
break;
case 'protocol_error':
text = 'Invalid protocol in the API url. Please, specify <b>http://</b> or ' +
'<b>https://</b>.';
break;
case 'unauthorized':
text = 'Credentials were found, but they are not valid.';
break;
case 'bad_url':
text = 'The given URL does not contain a valid Wazuh RESTful API installation.';
break;
case 'self_signed':
text = 'The request to Wazuh RESTful API was blocked, because it is using a ' +
'selfsigned SSL certificate. Please, enable <b>"Accept selfsigned SSL"</b> ' +
'option if you want to connect anyway.';
break;
case 'not_running':
text = 'There are not services running in the given URL.';
break;
default:
text = `Unexpected error. ${error.message}`;
}
notify.error(text);
$scope.messageError = text;
};
};
$scope.getAppInfo = function () {
$http.get("/api/wazuh-elastic/setup").then(function (data, status) {
$scope.getAppInfo = () => {
$http.get("/api/wazuh-elastic/setup")
.then((data) => {
$scope.appInfo = {};
$scope.appInfo["app-version"] = data.data.data["app-version"];
$scope.appInfo["app-version"] = data.data.data["app-version"];
$scope.appInfo["installationDate"] = data.data.data["installationDate"];
$scope.appInfo["revision"] = data.data.data["revision"];
}).catch(function (data, status) {
$scope.appInfo["revision"] = data.data.data["revision"];
})
.catch(() => {
notify.error("Error when loading Wazuh setup info");
})
}
});
};
// Loading data
$scope.getSettings();
$scope.getAppInfo();
});
});

21
public/less/agents.less Normal file
View File

@ -0,0 +1,21 @@
.agentsPreview {
margin: 10px;
}
.agentsPreview .md-whiteframe-z1 {
box-shadow: none;
}
md-list.agents-preview-table.even.ruleset_rules_row_active,
md-list.agents-preview-table.odd.ruleset_rules_row_active,
md-list.agents-preview-table.ruleset_rules_row_active:hover,
.md-button.agents-preview-table.buttonBlueLight.md-default-theme:not([disabled]):hover,
.md-button.agents-preview-table.buttonMenu.md-default-theme:not([disabled]):hover, {
background-color: #c2e4ef;
}
.agentsPreview md-input-container {
height: 41px;
margin-top: 17px;
padding: 2px;
}

View File

@ -22,7 +22,7 @@
}
.selectedItem {
background-color: rgba(129, 200, 222, 0.7) !important
background-color: rgba(129, 200, 222, 0.7) !important;
}
.list-no-hover > .md-button:not([disabled]):hover ,

35
public/less/kbn.less Normal file
View File

@ -0,0 +1,35 @@
kbn-vis-value td {
border: none !important;
padding: 0px;
}
kbn-vis-value thead,
kbn-vis-value .numeric-value,
kbn-vis-value .pagination-container,
kbn-vis-value h2,
kbn-vis-value .table .table-condensed td:nth-child(2) {
display: none;
}
kbn-vis-value .table {
margin-bottom: 0px;
}
kbn-vis-value .cell-hover {
color: rgba(0, 0, 0, 0.87);
font-size: 16pt;
border: none;
}
kbn-vis-value .agg-table-paginated .cell-hover:hover {
background-color: white;
}
kbn-vis-value .h4,
kbn-vis-value .h5,
kbn-vis-value .h6,
kbn-vis-value h4,
kbn-vis-value h5,
kbn-vis-value h6 {
margin: 0px;
}

7
public/less/loader.js Normal file
View File

@ -0,0 +1,7 @@
require('plugins/wazuh/less/agents.less');
require('plugins/wazuh/less/common.less');
require('plugins/wazuh/less/kbn.less');
require('plugins/wazuh/less/main.less');
require('plugins/wazuh/less/manager.less');
require('plugins/wazuh/less/media-queries.less');
require('plugins/wazuh/less/ruleset.less');

File diff suppressed because it is too large Load Diff

20
public/less/manager.less Normal file
View File

@ -0,0 +1,20 @@
.horizontal-menu-right .buttonMenu{
background-color: #3caed2;
color: white;
}
.horizontal-menu-right {
background-color: #f7f7f7
}
.managerConfigurationArrow {
float: right;
margin-top: 6px;
}
.joinCardsRow {
background-color: white;
margin: 8px;
margin-bottom: 5px;
margin-top: 10px;
}

View File

@ -0,0 +1,73 @@
@-webkit-keyframes uil-ring-anim {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-moz-keyframes uil-ring-anim {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-webkit-keyframes uil-ring-anim {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@-o-keyframes uil-ring-anim {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@keyframes uil-ring-anim {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
@media all and (-ms-high-contrast: none),
(-ms-high-contrast: active) {
.no-legend svg {
padding-top: 10px;
}
}
@supports (-ms-ime-align:auto) {
.no-legend svg {
padding-top: 10px;
}
}
@media (min-width: 960px) {
md-tooltip .md-content {
height: auto !important;
}
}

19
public/less/ruleset.less Normal file
View File

@ -0,0 +1,19 @@
.ruleset_card_info {
background-color: #dbf0f7
}
.ruleset_rules_row_active {
background-color: #c2e4ef;
}
.rules-item-list button.md-no-style.md-button.md-ink-ripple {
opacity: 0;
}
md-list-item.ruleset_rules_row_active {
background-color: #c2e4ef;
}
.listHover:hover {
font-weight: bold;
}

View File

@ -1,38 +1,42 @@
import chrome from 'ui/chrome';
require('ui/modules').get('app/wazuh', [])
.service('apiReq', function ($q, $http, genericReq) {
return {
request: function (method, path, body) {
var defered = $q.defer();
var promise = defered.promise;
require('ui/modules')
.get('app/wazuh', [])
.service('apiReq', function ($q, $http, genericReq) {
return {
request: (method, path, body) => {
let defered = $q.defer();
if (!method || !path || !body) {
defered.reject({ 'error': -1, 'message': 'Missing parameters' });
return promise;
}
var requestData = {
'method': method,
'path': path,
'body': body
}
genericReq.request('POST', '/api/wazuh-api/request', requestData)
.then(function (data) {
if (data.error) {
defered.reject(data);
} else {
defered.resolve(data);
}
}, function (data) {
if (data.error) {
defered.reject(data);
} else {
defered.reject({ 'error': -2, 'message': 'Error doing a request to Kibana API.' });
}
});
return promise;
if (!method || !path || !body) {
defered.reject({
error: -1,
message: 'Missing parameters'
});
return defered.promise;
}
};
});
let requestData = { method, path, body };
genericReq
.request('POST', '/api/wazuh-api/request', requestData)
.then((data) => {
if (data.error) {
defered.reject(data);
} else {
defered.resolve(data);
}
})
.catch((error) => {
if (error.error) {
defered.reject(error);
} else {
defered.reject({
error: -2,
message: 'Error doing a request to Kibana API.'
});
}
});
return defered.promise;
}
};
});

View File

@ -1,75 +1,83 @@
require('ui/modules').get('app/wazuh', [])
.service('appState', function ($cookies) {
return {
getDashboardsState: function () {
return { name: $cookies.getObject('_dashboardsState_name'), filter: $cookies.getObject('_dashboardsState_filter') };
},
setDashboardsState: function (name, filter) {
if (name) {
$cookies.putObject('_dashboardsState_name', name);
}
if (filter) {
$cookies.putObject('_dashboardsState_filter', filter);
}
},
getExtensions: function () {
return { extensions: $cookies.getObject('extensions') };
},
setExtensions: function (extensions) {
if (extensions) {
$cookies.putObject('extensions', extensions);
}
},
unsetDashboardsState: function () {
$cookies.putObject('_dashboardsState_name', "");
$cookies.putObject('_dashboardsState_filter', "");
},
getDiscoverState: function () {
return { name: $cookies.getObject('_discoverState_name'), filter: $cookies.getObject('_discoverState_filter') };
},
setDiscoverState: function (name, filter) {
if (name) {
$cookies.putObject('_discoverState_name', name);
}
if (filter) {
$cookies.putObject('_discoverState_filter', filter);
}
},
unsetDiscoverState: function () {
$cookies.putObject('_discoverState_name', "");
$cookies.putObject('_discoverState_filter', "");
},
getManagerState: function () {
return $cookies.getObject('_managerState');
},
setManagerState: function (subtab) {
if (subtab) {
$cookies.putObject('_managerState', subtab);
}
},
getRulesetState: function () {
return $cookies.getObject('_rulesetState');
},
setRulesetState: function (subtab) {
if (subtab) {
$cookies.putObject('_rulesetState', subtab);
}
},
getOverviewState: function () {
return $cookies.getObject('_overviewState');
},
setOverviewState: function (subtab) {
if (subtab) {
$cookies.putObject('_overviewState', subtab);
}
},
getClusterInfo: function () {
return $cookies.getObject('_clusterInfo');
},
setClusterInfo: function (cluster_info) {
if (cluster_info) {
$cookies.putObject('_clusterInfo', cluster_info);
}
}
};
});
.service('appState', function ($cookies) {
return {
getDashboardsState: () => {
return {
name: $cookies.getObject('_dashboardsState_name'),
filter: $cookies.getObject('_dashboardsState_filter')
};
},
setDashboardsState: (name, filter) => {
if (name) {
$cookies.putObject('_dashboardsState_name', name);
}
if (filter) {
$cookies.putObject('_dashboardsState_filter', filter);
}
},
getExtensions: () => {
return {
extensions: $cookies.getObject('extensions')
};
},
setExtensions: (extensions) => {
if (extensions) {
$cookies.putObject('extensions', extensions);
}
},
unsetDashboardsState: () => {
$cookies.putObject('_dashboardsState_name', "");
$cookies.putObject('_dashboardsState_filter', "");
},
getDiscoverState: () => {
return {
name: $cookies.getObject('_discoverState_name'),
filter: $cookies.getObject('_discoverState_filter')
};
},
setDiscoverState: (name, filter) => {
if (name) {
$cookies.putObject('_discoverState_name', name);
}
if (filter) {
$cookies.putObject('_discoverState_filter', filter);
}
},
unsetDiscoverState: () => {
$cookies.putObject('_discoverState_name', "");
$cookies.putObject('_discoverState_filter', "");
},
getManagerState: () => {
return $cookies.getObject('_managerState');
},
setManagerState: (subtab) => {
if (subtab) {
$cookies.putObject('_managerState', subtab);
}
},
getRulesetState: () => {
return $cookies.getObject('_rulesetState');
},
setRulesetState: (subtab) => {
if (subtab) {
$cookies.putObject('_rulesetState', subtab);
}
},
getOverviewState: () => {
return $cookies.getObject('_overviewState');
},
setOverviewState: (subtab) => {
if (subtab) {
$cookies.putObject('_overviewState', subtab);
}
},
getClusterInfo: () => {
return $cookies.getObject('_clusterInfo');
},
setClusterInfo: (cluster_info) => {
if (cluster_info) {
$cookies.putObject('_clusterInfo', cluster_info);
}
}
};
});

View File

@ -1,108 +1,134 @@
var app = require('ui/modules').get('app/wazuh', []);
let app = require('ui/modules').get('app/wazuh', []);
app.factory('DataHandler', function($q, apiReq) {
var DataHandler = function() {
this.items = [];
this.filters = [];
this.path = '';
this.offset = 0;
this.sortValue = '';
this.initial = true;
this.initialBatch = 40;
this.regularBatch = 15;
};
app.factory('DataHandler', function ($q, apiReq) {
class DataHandler {
constructor() {
this.items = [];
this.filters = [];
this.path = '';
this.offset = 0;
this.sortValue = '';
this.initial = true;
this.initialBatch = 40;
this.regularBatch = 15;
}
DataHandler.prototype.nextPage = function() {
if (this.busy) return;
this.busy = true;
var requestData;
nextPage () {
if (this.busy) return;
this.busy = true;
let requestData;
if (this.initial) { requestData = { offset: this.offset, limit: this.initialBatch }; this.initial = false; }
else requestData = { offset: this.offset, limit: this.regularBatch };
if (this.initial) {
requestData = {
offset: this.offset,
limit: this.initialBatch
};
this.initial = false;
} else {
requestData = {
offset: this.offset,
limit: this.regularBatch
};
}
angular.forEach(this.filters, function(filter) {
if (filter.value != '') requestData[filter.name] = filter.value;
});
for(let filter of this.filters){
if (filter.value !== '') requestData[filter.name] = filter.value;
}
var deferred = $q.defer();
apiReq.request('GET', this.path, requestData).then(function(data) {
if (data.data.data == 0)
deferred.resolve(false);
let deferred = $q.defer();
apiReq.request('GET', this.path, requestData)
.then(function (data) {
if (data.data.data === 0){
deferred.resolve(false);
}
let totalItems = data.data.data.totalItems;
let items = data.data.data.items;
for (let i = 0,len = items.length; i < len; i++) {
this.items.push(items[i]);
this.items[i].selected = false;
}
this.offset += items.length;
(this.offset >= totalItems) ? this.end = true: this.busy = false;
if (data.data.data !== 0){
deferred.resolve(true);
}
}.bind(this));
var totalItems = data.data.data.totalItems;
var items = data.data.data.items;
for (var i = 0; i < items.length; i++) {
this.items.push(items[i]); this.items[i].selected = false;
}
this.offset += items.length;
(this.offset >= totalItems) ? this.end = true : this.busy = false
if (data.data.data != 0)
deferred.resolve(true);
return deferred.promise;
}
}.bind(this));
return deferred.promise;
};
hasFilter (filterName) {
let filtered = this.filters.filter((element) => element.name === filterName);
return filtered.length !== 0;
}
DataHandler.prototype.hasFilter = function(filterName) {
var filterOrNot = false;
angular.forEach(this.filters, function(filter) { if (filter.name == filterName) filterOrNot = true; });
return filterOrNot;
};
addFilter (filterName, value) {
this.removeFilter(filterName, false);
this.filters.push({
name: filterName,
value: value
});
this.search();
}
DataHandler.prototype.addFilter = function(filterName, value) {
this.removeFilter(filterName, false);
this.filters.push({ "name": filterName, "value": value });
this.search();
};
removeFilter (filterName, search) {
angular.forEach(this.filters, function (filter, key) {
if (filterName === filter.name) {
this.filters.splice(key, 1);
}
}, this);
if (search) this.search();
}
DataHandler.prototype.removeFilter = function(filterName, search) {
angular.forEach(this.filters, function(filter, key) {
if (filterName == filter.name) { this.filters.splice(key, 1); }
}, this);
if (search) this.search();
};
delete (name, index) {
apiReq.request('DELETE', this.path, {})
.then(function (data) {
this.items.splice(index, 1);
}.bind(this));
}
DataHandler.prototype.delete = function(name, index) {
apiReq.request('DELETE', this.path, {}).then(function(data) {
this.items.splice(index, 1);
}.bind(this));
};
search () {
let requestData;
this.end = false;
this.busy = false;
this.sortValue = '';
DataHandler.prototype.search = function() {
var requestData;
this.end = false; this.busy = false;
this.sortValue = '';
requestData = {
offset: 0,
limit: this.initialBatch
};
requestData = { offset: 0, limit: this.initialBatch }
for(let filter of this.filters){
if (filter.value !== '') requestData[filter.name] = filter.value;
}
angular.forEach(this.filters, function(filter) {
if (filter.value != '') requestData[filter.name] = filter.value;
});
apiReq.request('GET', this.path, requestData)
.then(function (data) {
this.items = [];
let items = data.data.data.items;
for (let i = 0,len = items.length; i < len; i++) {
this.items.push(items[i]);
this.items[i].selected = false;
}
this.offset = items.length;
}.bind(this));
}
apiReq.request('GET', this.path, requestData).then(function(data) {
this.items = [];
var items = data.data.data.items;
for (var i = 0; i < items.length; i++) {
this.items.push(items[i]); this.items[i].selected = false;
}
this.offset = items.length;
}.bind(this));
};
sort(by) {
this.sortValue = by;
this.sortDir = !this.sortDir;
}
DataHandler.prototype.sort = function(by) {
this.sortValue = by;
this.sortDir = !this.sortDir;
};
reset() {
this.items = [];
this.filters = [];
this.offset = 0;
this.sortValue = '';
this.initial = true;
this.end = false;
this.busy = false;
}
}
DataHandler.prototype.reset = function() {
this.items = [];
this.filters = [];
this.offset = 0;
this.sortValue = '';
this.initial = true;
this.end = false;
this.busy = false;
};
return DataHandler;
});
return DataHandler;
});

View File

@ -1,137 +1,78 @@
const prepError = require('plugins/wazuh/services/prep-error');
import chrome from 'ui/chrome';
require('ui/modules').get('app/wazuh', [])
.service('genericReq', function ($q, $http) {
var _request = function (method, url, payload = null) {
var defered = $q.defer();
var promise = defered.promise;
const _request = (method, url, payload = null) => {
let defered = $q.defer();
if (!method || !url) {
defered.reject({ 'error': -1, 'message': 'Missing parameters' });
return promise;
}
var requestHeaders = {
headers: {
"Content-Type": 'application/json'
}
}
if (method == "GET") {
$http.get(chrome.addBasePath(url), requestHeaders)
.then(function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.resolve(data);
}
}, function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.reject({ 'error': -2, 'message': 'Error doing a request to Kibana API.' });
}
});
}
if (method == "PUT") {
$http.put(chrome.addBasePath(url), payload, requestHeaders)
.then(function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.resolve(data);
}
}, function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.reject({ 'error': -2, 'message': 'Error doing a request to Kibana API.' });
}
});
}
if (method == "POST") {
$http.post(chrome.addBasePath(url), payload, requestHeaders)
.then(function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.resolve(data);
}
}, function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.reject({ 'error': -2, 'message': 'Error doing a request to Kibana API.' });
}
});
defered.reject({
'error': -1,
'message': 'Missing parameters'
});
return defered.promise;
}
if (method == "DELETE") {
$http.delete(chrome.addBasePath(url))
.then(function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.resolve(data);
}
},function (data) {
if (data.error && data.error != '0') {
defered.reject(data);
} else {
defered.reject({ 'error': -2, 'message': 'Error doing a request to Kibana API.' });
}
});
}
return promise;
};
let requestHeaders = { headers: { "Content-Type": 'application/json' } };
var prepError = function (err) {
if (err.error < 0) {
err['html'] = "Unexpected error located on controller. Error: <b>" + err.message + " (code " + err.error + ")</b>.";
err.message = "Unexpected error located on controller. Error: " + err.message + " (code " + err.error + ").";
} else if (err.error === 1) {
err['html'] = "<b>Error getting credentials</b> for Wazuh API. Please, check credentials at settings tab.";
err.message = "Error getting credentials for Wazuh API. Please, check credentials at settings tab.";
} else if (err.error === 2) {
err['html'] = "<b>Error getting credentials</b> for Wazuh API. Could not connect with Elasticsearch.";
err.message = "Error getting credentials for Wazuh API. Could not connect with Elasticsearch.";
} else if (err.error < 5) {
err['html'] = "Unexpected error located on Kibana server. Error: <b>" + err.message + " (code " + err.error + ")</b>.";
err.message = "Unexpected error located on Kibana server. Error: " + err.message + " (code " + err.error + ").";
} else if (err.error === 5) {
err['html'] = "Could not connect with Wazuh API. Error: " + err.errorMessage + ".</br> Please, check the URL at settings tab.";
err.message = "Could not connect with Wazuh API. Error: " + err.errorMessage + ". Please, check the URL at settings tab.";
} else if (err.error === 6) {
if (err.errorData.statusCode && err.errorData.statusCode == '404') {
err['html'] = "Wazuh API URL could not be found on elasticsearch. Please, configure the application properly.";
err.message = "Wazuh API URL could not be found on elasticsearch. Please, configure the application properly.";
let tmpUrl = chrome.addBasePath(url), tmp = null;
if (method === "GET") tmp = $http.get(tmpUrl, requestHeaders);
if (method === "PUT") tmp = $http.put(tmpUrl, payload, requestHeaders);
if (method === "POST") tmp = $http.post(tmpUrl, payload, requestHeaders);
if (method === "DELETE") tmp = $http.delete(tmpUrl);
if(!tmp) {
defered.reject({
'error': -2,
'message': 'Error doing a request to Kibana API.'
});
return defered.promise;
}
tmp
.then((data) => {
if (data.error && data.error !== '0') {
defered.reject(data);
} else {
err['html'] = "Wazuh API returned an error message. Error: <b>" + err.errorData.message + "</b>";
err.message = "Wazuh API returned an error message. Error: " + err.errorData.message;
defered.resolve(data);
}
} else if (err.error === 7) {
err['html'] = "Unexpected error filtering the data. Error <b>" + err.message + "</b>.";
err.message = "Unexpected error filtering the data. Error " + err.message + ".";
} else {
err['html'] = "Unexpected error. Please, report this error.";
err.message = "Unexpected error. Please, report this error.";
}
})
.catch((error) => {
console.dir(error);
if (error.error && error.error !== '0') {
defered.reject(error);
} else {
defered.reject({
'error': -2,
'message': 'Error doing a request to Kibana API.'
});
}
});
return err;
return defered.promise;
};
return {
request: function (method, path, payload = null) {
var defered = $q.defer();
var promise = defered.promise;
request: (method, path, payload = null) => {
let defered = $q.defer();
if (!method || !path) {
defered.reject(prepError({ 'error': -1, 'message': 'Missing parameters' }));
return promise;
defered.reject(prepError({
'error': -1,
'message': 'Missing parameters'
}));
return defered.promise;
}
_request(method, path, payload)
.then(function (data) {
defered.resolve(data);
}, function (data) {
defered.reject(prepError(data));
});
return promise;
.then((data) => defered.resolve(data))
.catch((error) => defered.reject(prepError(error)));
return defered.promise;
}
};
});
});

View File

@ -0,0 +1,34 @@
module.exports = (err) => {
if (parseInt(err.error) < 0) {
err['html'] = `Unexpected error located on controller. Error: <b>${err.message} (code ${err.error})</b>.`;
err.message = `Unexpected error located on controller. Error: ${err.message} (code ${err.error}).`;
} else if (parseInt(err.error) === 1) {
err['html'] = "<b>Error getting credentials</b> for Wazuh API. Please, check credentials at settings tab.";
err.message = "Error getting credentials for Wazuh API. Please, check credentials at settings tab.";
} else if (parseInt(err.error) === 2) {
err['html'] = "<b>Error getting credentials</b> for Wazuh API. Could not connect with Elasticsearch.";
err.message = "Error getting credentials for Wazuh API. Could not connect with Elasticsearch.";
} else if (parseInt(err.error) < 5) {
err['html'] = `Unexpected error located on Kibana server. Error: <b>${err.message} (code ${err.error})</b>.`;
err.message = `Unexpected error located on Kibana server. Error: ${err.message} (code ${err.error}).`;
} else if (parseInt(err.error) === 5) {
err['html'] = `Could not connect with Wazuh API. Error: ${err.errorMessage}.</br> Please, check the URL at settings tab.`;
err.message = `Could not connect with Wazuh API. Error: ${err.errorMessage}. Please, check the URL at settings tab.`;
} else if (parseInt(err.error) === 6) {
if (err.errorData.statusCode && err.errorData.statusCode === '404') {
err['html'] = "Wazuh API URL could not be found on elasticsearch. Please, configure the application properly.";
err.message = "Wazuh API URL could not be found on elasticsearch. Please, configure the application properly.";
} else {
err['html'] = `Wazuh API returned an error message. Error: <b>${err.errorData.message}</b>`;
err.message = `Wazuh API returned an error message. Error: ${err.errorData.message}`;
}
} else if (parseInt(err.error) === 7) {
err['html'] = `Unexpected error filtering the data. Error <b>${err.message}</b>.`;
err.message = `Unexpected error filtering the data. Error ${err.message}.`;
} else {
err['html'] = "Unexpected error. Please, report this error.";
err.message = "Unexpected error. Please, report this error.";
}
return err;
};

View File

@ -1,41 +1,45 @@
// Require routes
var routes = require('ui/routes');
let routes = require('ui/routes');
//Installation wizard
var settingsWizard = function ($location, $q, Notifier, testAPI, appState) {
const notify = new Notifier();
const settingsWizard = ($location, $q, Notifier, testAPI, appState) => {
const notify = new Notifier();
var deferred = $q.defer();
testAPI.check_stored().then(
function (data) {
if (data.data.error) {
if(data.data.error == 2)
notify.warning("Wazuh App: Please set up Wazuh API credentials.");
else
notify.error("Could not connect with Wazuh RESTful API.");
deferred.reject();
$location.path('/settings');
let deferred = $q.defer();
testAPI.check_stored()
.then((data) => {
if (data.data.error) {
if (parseInt(data.data.error) === 2){
notify.warning("Wazuh App: Please set up Wazuh API credentials.");
} else {
appState.setClusterInfo(data.data.data.cluster_info);
appState.setExtensions(data.data.data.extensions);
deferred.resolve();
notify.error("Could not connect with Wazuh RESTful API.");
}
}, function (data) {
notify.error("Could not connect with Wazuh RESTful API.");
});
$location.path('/settings');
deferred.reject();
} else {
appState.setClusterInfo(data.data.data.cluster_info);
appState.setExtensions(data.data.data.extensions);
deferred.resolve();
}
});
return deferred.promise;
}
};
// Manage leaving the app to another Kibana tab
var goToKibana = function ($location, $window) {
var url = $location.$$absUrl.substring(0, $location.$$absUrl.indexOf('#'));
if(sessionStorage.getItem('lastSubUrl:' + url).includes('/wazuh#/visualize') || sessionStorage.getItem('lastSubUrl:' + url).includes('/wazuh#/doc') || sessionStorage.getItem('lastSubUrl:' + url).includes('/wazuh#/context'))
sessionStorage.setItem('lastSubUrl:' + url, url);
const goToKibana = ($location, $window) => {
let url = $location.$$absUrl.substring(0, $location.$$absUrl.indexOf('#'));
if (sessionStorage.getItem(`lastSubUrl:${url}`).includes('/wazuh#/visualize') ||
sessionStorage.getItem(`lastSubUrl:${url}`).includes('/wazuh#/doc') ||
sessionStorage.getItem(`lastSubUrl:${url}`).includes('/wazuh#/context')){
sessionStorage.setItem(`lastSubUrl:${url}`, url);
}
$window.location.href = $location.absUrl().replace('/wazuh#', '/kibana#');
}
};
//Routes
routes.enable();
@ -52,7 +56,7 @@ routes
"checkAPI": settingsWizard
}
})
.when('/overview/', {
.when('/overview/', {
template: require('plugins/wazuh/templates/overview.jade'),
resolve: {
"checkAPI": settingsWizard
@ -64,7 +68,7 @@ routes
"checkAPI": settingsWizard
}
})
.when('/discover/', {
.when('/discover/', {
template: require('plugins/wazuh/templates/discover.jade'),
resolve: {
"checkAPI": settingsWizard
@ -74,22 +78,19 @@ routes
template: require('plugins/wazuh/templates/settings.html')
})
.when('/visualize/create?', {
redirectTo: function() {
},
redirectTo: function () {},
resolve: {
"checkAPI": goToKibana
}
})
.when('/context/:pattern?/:type?/:id?', {
redirectTo: function() {
},
redirectTo: function () {},
resolve: {
"checkAPI": goToKibana
}
})
.when('/doc/:pattern?/:index?/:type?/:id?', {
redirectTo: function() {
},
redirectTo: function () {},
resolve: {
"checkAPI": goToKibana
}
@ -102,4 +103,4 @@ routes
})
.otherwise({
redirectTo: '/overview/'
});
});

View File

@ -1,36 +1,40 @@
import chrome from 'ui/chrome';
require('ui/modules').get('app/wazuh', [])
.service('testAPI', function ($q, $http) {
return {
check_stored: function () {
var defered = $q.defer();
$http.get(chrome.addBasePath("/api/wazuh-api/checkAPI")).then(function successCallback(response) {
if (response.error) {
defered.reject(response);
} else {
defered.resolve(response);
}
}, function errorCallback(response) {
if (response.error) {
defered.reject(response);
}
});
return defered.promise;
},
check: function (data) {
var defered = $q.defer();
$http.post(chrome.addBasePath("/api/wazuh-api/checkAPI"), data).then(function successCallback(response) {
if (response.error) {
defered.reject(response);
} else {
defered.resolve(response);
}
}, function errorCallback(response) {
if (response.error) {
defered.reject(response);
}
});
return defered.promise;
}
};
});
.service('testAPI', function ($q, $http) {
return {
check_stored: () => {
let defered = $q.defer();
$http.get(chrome.addBasePath('/api/wazuh-api/checkAPI'))
.then((response) => {
if (response.error) {
defered.reject(response);
} else {
defered.resolve(response);
}
})
.catch((error) => {
if (error.error) {
defered.reject(error);
}
});
return defered.promise;
},
check: (data) => {
let defered = $q.defer();
$http.post(chrome.addBasePath("/api/wazuh-api/checkAPI"), data)
.then((response) => {
if (response.error) {
defered.reject(response);
} else {
defered.resolve(response);
}
})
.catch((error) => {
if (error.error) {
defered.reject(error);
}
});
return defered.promise;
}
};
});

View File

@ -1,70 +1,70 @@
require('ui/modules').get('app/wazuh', [])
.config(function ($mdThemingProvider) {
.config(function ($mdThemingProvider) {
var kibanaWhiteBlack = {
'50': '#ffffff',
'100': '#ffffff',
'200': '#ffffff',
'300': '#ffffff',
'400': '#fafafa',
'500': '#ecf0f1',
'600': '#dde4e6',
'700': '#cfd9db',
'800': '#c0cdd1',
'900': '#000000',
'A100': '#ffffff',
'A200': '#ffffff',
'A400': '#ffffff',
'A700': '#a3b6bb'
};
$mdThemingProvider
.definePalette('kibanaWhiteBlack',
kibanaWhiteBlack);
let kibanaWhiteBlack = {
'50': '#ffffff',
'100': '#ffffff',
'200': '#ffffff',
'300': '#ffffff',
'400': '#fafafa',
'500': '#ecf0f1',
'600': '#dde4e6',
'700': '#cfd9db',
'800': '#c0cdd1',
'900': '#000000',
'A100': '#ffffff',
'A200': '#ffffff',
'A400': '#ffffff',
'A700': '#a3b6bb'
};
var kibanaBlue = {
'50': '#a4d9ea',
'100': '#8fd0e5',
'200': '#7ac8e0',
'300': '#65bfdc',
'400': '#51b7d7',
'500': '#3caed2',
'600': '#2ea2c7',
'700': '#2991b2',
'800': '#24809d',
'900': '#206f88',
'A100': '#b8e2ef',
'A200': '#cdeaf3',
'A400': '#e2f3f8',
'A700': '#1b5e74',
'contrastDefaultColor': 'dark',
};
$mdThemingProvider
.definePalette('kibanaBlue',
$mdThemingProvider.definePalette('kibanaWhiteBlack', kibanaWhiteBlack);
let kibanaBlue = {
'50': '#a4d9ea',
'100': '#8fd0e5',
'200': '#7ac8e0',
'300': '#65bfdc',
'400': '#51b7d7',
'500': '#3caed2',
'600': '#2ea2c7',
'700': '#2991b2',
'800': '#24809d',
'900': '#206f88',
'A100': '#b8e2ef',
'A200': '#cdeaf3',
'A400': '#e2f3f8',
'A700': '#1b5e74',
'contrastDefaultColor': 'dark'
};
$mdThemingProvider
.definePalette('kibanaBlue',
kibanaBlue);
$mdThemingProvider.theme('default')
.primaryPalette('blue-grey', {
'default': '100',
'hue-1': '300',
'hue-2': '500',
'hue-3': '700'
})
.accentPalette('kibanaBlue', {
'default': '500',
'hue-1': '800',
'hue-2': '300',
'hue-3': '100'
})
.warnPalette('amber', {
'default': '300',
'hue-1': '500',
'hue-2': '700',
'hue-3': '900'
})
.backgroundPalette('kibanaWhiteBlack', {
'default': '50',
'hue-1': '50',
'hue-2': '600',
'hue-3': '900'
})
});
$mdThemingProvider.theme('default')
.primaryPalette('blue-grey', {
'default': '100',
'hue-1': '300',
'hue-2': '500',
'hue-3': '700'
})
.accentPalette('kibanaBlue', {
'default': '500',
'hue-1': '800',
'hue-2': '300',
'hue-3': '100'
})
.warnPalette('amber', {
'default': '300',
'hue-1': '500',
'hue-2': '700',
'hue-3': '900'
})
.backgroundPalette('kibanaWhiteBlack', {
'default': '50',
'hue-1': '50',
'hue-2': '600',
'hue-3': '900'
});
});

View File

@ -66,10 +66,10 @@
</div>
<div layout="row" class="sideNavBox" flex="20">
<md-input-container flex class="md-whiteframe-z1">
<md-select id="eventBox" ng-model="osPlatform" ng-change="agents.addFilter('os.name', osPlatform)" aria-label="Filter by operative system">
<md-select id="eventBox" ng-model="osPlatform" ng-change="agents.addFilter('os.platform', osPlatform)" aria-label="Filter by operative system">
<md-option value="all">All OS platforms</md-option>
<md-option ng-repeat='platform in osPlatforms' value="{{platform}}">
{{platform}}
<md-option ng-repeat='platform in osPlatforms' value="{{platform.platform}}">
{{platform.name}}
</md-option>
</md-select>
</md-input-container>

View File

@ -1,5 +1,4 @@
<div flex ng-cloak layout="row" ng-controller="groupsPreviewController" layout-align="space-around" style="background-color: #e3e3e3;"
ng-if="groupsMenu == 'preview'">
<div flex ng-cloak layout="row" ng-controller="groupsPreviewController" layout-align="space-around" style="background-color: #e3e3e3;" ng-if="groupsMenu == 'preview'">
<div flex="25" layout="column">
<md-card flex style="background-color:#E4E4E4; overflow: auto; height:400px; overflow-y: scroll;" when-scrolled="groups.nextPage('')">
@ -111,4 +110,5 @@ ng-if="groupsMenu == 'preview'">
</md-tabs>
</div>
</div>

View File

@ -1,56 +1,61 @@
<div flex ng-cloak ng-if="!loading && submenuNavItem == 'logs'" layout="column" ng-controller="managerLogController">
<div layout="row" layout-align="start start" class="horizontal-menu-right" style="background: #f7f7f7; height: 70px;">
<md-input-container class="md-whiteframe-z1" flex="20" style="margin-right: 15px;margin-left: 20px;padding: 3px;margin-right: 10px;">
<md-select id="categoryBox" ng-model="category" ng-change="category == 'all' ? logs.removeFilter('category', true) : logs.addFilter('category', category)" aria-label="Logs category">
<md-option selected value="all">Choose daemon</md-option>
<md-option ng-repeat="(key, value) in summary" value="{{key}}">{{key}}</md-option>
</md-select>
</md-input-container>
<div layout="row" layout-align="start start" class="horizontal-menu-right" style="background: #f7f7f7; height: 70px;">
<md-input-container class="md-whiteframe-z1" flex="20" style="margin-right: 15px;margin-left: 20px;padding: 3px;margin-right: 10px;">
<md-select id="categoryBox" ng-model="category" ng-change="category == 'all' ? logs.removeFilter('category', true) : logs.addFilter('category', category)"
aria-label="Logs category">
<md-option selected value="all">Choose daemon</md-option>
<md-option ng-repeat="(key, value) in summary" value="{{key}}">{{key}}</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-whiteframe-z1" flex="20" style="margin-right: 0px;margin-left: 20px;padding: 3px;margin-right: 10px;">
<md-select id="levelBox" ng-model="type_log" ng-change="type_log == 'all' ? logs.removeFilter('type_log', true) : logs.addFilter('type_log', type_log)" aria-label="Logs level">
<md-option selected value="all">Choose log level</md-option>
<md-option value="info">Info</md-option>
<md-option value="error">Error</md-option>
</md-select>
</md-input-container>
<md-input-container class="md-whiteframe-z1" flex="20" style="margin-right: 0px;margin-left: 20px;padding: 3px;margin-right: 10px;">
<md-select id="levelBox" ng-model="type_log" ng-change="type_log == 'all' ? logs.removeFilter('type_log', true) : logs.addFilter('type_log', type_log)"
aria-label="Logs level">
<md-option selected value="all">Choose log level</md-option>
<md-option value="info">Info</md-option>
<md-option value="error">Error</md-option>
<md-option value="warning">Warning</md-option>
</md-select>
</md-input-container>
<div flex layout="row" layout-align="end end">
<span>
<md-button ng-if="!realtime" class="md-primary md-whiteframe-z1 buttonMenu" ng-click="playRealtime()" style="margin-top: 20px; width: 180px">
<i class="fa fa-play" aria-hidden="true" style="margin-top: 0px; margin-right: 15px; margin-bottom: 5px;"></i>
Play realtime
</md-button>
<md-button style="margin-top: 20px; width: 180px" ng-if="realtime" class="md-primary md-whiteframe-z1 buttonMenu" ng-click="playRealtime()">
<i class="fa fa-stop" aria-hidden="true" style="margin-top: 0px; margin-right: 15px; margin-bottom: 5px;"></i>
Stop realtime
</md-button>
</span>
<div flex layout="row" layout-align="end end">
<span>
<md-button ng-if="!realtime" class="md-primary md-whiteframe-z1 buttonMenu" ng-click="playRealtime()" style="margin-top: 20px; width: 180px">
<i class="fa fa-play" aria-hidden="true" style="margin-top: 0px; margin-right: 15px; margin-bottom: 5px;"></i>
Play realtime
</md-button>
<md-button style="margin-top: 20px; width: 180px" ng-if="realtime" class="md-primary md-whiteframe-z1 buttonMenu" ng-click="playRealtime()">
<i class="fa fa-stop" aria-hidden="true" style="margin-top: 0px; margin-right: 15px; margin-bottom: 5px;"></i>
Stop realtime
</md-button>
</span>
</div>
</div>
</div>
<input placeholder="Filter" type="text" ng-model="searchTerm" ng-change="logs.addFilter('search', searchTerm)" style="height: 55px;">
<input placeholder="Filter" type="text" ng-model="searchTerm" ng-change="logs.addFilter('search', searchTerm)" class="input-filter-box"
style="height: 35px; width:auto; margin: 5px;">
<md-toolbar flex layout="row" class="md-toolbar-tools">
<span flex=10>Timestamp</span>
<span flex=10>Tag</span>
<span flex=10>Level</span>
<span flex>Description</span>
</md-toolbar>
<md-toolbar flex layout="row" class="md-toolbar-tools">
<span flex=10>Timestamp</span>
<span flex=10>Tag</span>
<span flex=10>Level</span>
<span flex>Description</span>
</md-toolbar>
<div flex layout="row">
<div layout="column" flex>
<div flex style="overflow: auto; height:400px;" id="groups-id" layout="column" when-scrolled="logs.nextPage('')">
<md-list>
<md-list-item ng-repeat="log in logs.items | filter : searchTerm" ng-mouseover="log.hovered=true" ng-mouseleave="log.hovered=false" layout="row" class="groups-button">
<span flex= 10>{{log.timestamp}}</span>
<span flex= 10>{{log.tag}}</span>
<span flex= 10>{{log.level}}</span>
<span flex>{{log.description}}</span>
<div flex layout="row" layout-align="end center"></div>
</md-list-item>
</md-list>
</div>
<div flex layout="row">
<div layout="column" flex>
<div flex style="overflow: auto; height:400px;" id="groups-id" layout="column" when-scrolled="logs.nextPage('')">
<md-list>
<md-list-item ng-repeat="log in logs.items | filter : searchTerm" ng-mouseover="log.hovered=true" ng-mouseleave="log.hovered=false"
layout="row" class="groups-button">
<span flex=10>{{log.timestamp}}</span>
<span flex=10>{{log.tag}}</span>
<span flex=10>{{log.level}}</span>
<span flex>{{log.description}}</span>
<div flex layout="row" layout-align="end center"></div>
</md-list-item>
</md-list>
</div>
</div>
</div>
</div>
</div>
</div>

View File

@ -43,7 +43,7 @@ module.exports = (server, options) => {
q: 'active:true'
})
.then((data) => {
if (data.hits.total == 1) {
if (data.hits.total === 1) {
// Setting off previous default
elasticRequest.callWithRequest(req, 'update', {
index: '.wazuh',
@ -61,22 +61,22 @@ module.exports = (server, options) => {
id: req.params.id,
body: {
doc: {
"active": "true"
"active": 'true'
}
}
})
)
.then(() => {
reply({
'statusCode': 200,
'message': 'ok'
statusCode: 200,
message: 'ok'
});
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 8,
'message': 'Could not save data in elasticsearch'
statusCode: 500,
error: 8,
message: 'Could not save data in elasticsearch'
}).code(500);
});
} else {
@ -133,7 +133,7 @@ module.exports = (server, options) => {
const toggleExtension = (req, reply) => {
// Toggle extenion state
let extension = {};
extension[req.params.extensionName] = (req.params.extensionValue === 'true') ? true : false;
extension[req.params.extensionName] = (req.params.extensionValue === 'true');
elasticRequest
.callWithRequest(req, 'update', {
@ -176,15 +176,15 @@ module.exports = (server, options) => {
}
let settings = {
'api_user': req.payload.user,
'api_password': req.payload.password,
'url': req.payload.url,
'api_port': req.payload.port,
'insecure': req.payload.insecure,
'component': 'API',
'active': req.payload.active,
'cluster_info': req.payload.cluster_info,
'extensions': req.payload.extensions
api_user: req.payload.user,
api_password: req.payload.password,
url: req.payload.url,
api_port: req.payload.port,
insecure: req.payload.insecure,
component: 'API',
active: req.payload.active,
cluster_info: req.payload.cluster_info,
extensions: req.payload.extensions
};
elasticRequest
@ -197,16 +197,16 @@ module.exports = (server, options) => {
})
.then((response) => {
reply({
'statusCode': 200,
'message': 'ok',
'response': response
statusCode: 200,
message: 'ok',
response: response
});
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 8,
'message': 'Could not save data in elasticsearch'
statusCode: 500,
error: 8,
message: 'Could not save data in elasticsearch'
}).code(500);
});
};
@ -225,15 +225,15 @@ module.exports = (server, options) => {
})
.then(() => {
reply({
'statusCode': 200,
'message': 'ok'
statusCode: 200,
message: 'ok'
});
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 8,
'message': 'Could not save data in elasticsearch'
statusCode: 500,
error: 8,
message: 'Could not save data in elasticsearch'
}).code(500);
});
};
@ -246,8 +246,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'PUT',
path: '/api/wazuh-api/settings',
method: 'PUT',
path: '/api/wazuh-api/settings',
handler: saveAPI
});
@ -257,8 +257,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-api/apiEntries',
method: 'GET',
path: '/api/wazuh-api/apiEntries',
handler: getAPIEntries
});
@ -268,8 +268,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'DELETE',
path: '/api/wazuh-api/apiEntries/{id}',
method: 'DELETE',
path: '/api/wazuh-api/apiEntries/{id}',
handler: deleteAPIEntries
});
@ -279,8 +279,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'PUT',
path: '/api/wazuh-api/apiEntries/{id}',
method: 'PUT',
path: '/api/wazuh-api/apiEntries/{id}',
handler: setAPIEntryDefault
});
@ -291,8 +291,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'PUT',
path: '/api/wazuh-api/extension/toggle/{id}/{extensionName}/{extensionValue}',
method: 'PUT',
path: '/api/wazuh-api/extension/toggle/{id}/{extensionName}/{extensionValue}',
handler: toggleExtension
});
@ -302,8 +302,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-api/extension',
method: 'GET',
path: '/api/wazuh-api/extension',
handler: getExtensions
});
@ -313,8 +313,8 @@ module.exports = (server, options) => {
*
**/
server.route({
method: 'PUT',
path: '/api/wazuh-api/updateApiHostname/{id}',
method: 'PUT',
path: '/api/wazuh-api/updateApiHostname/{id}',
handler: updateAPIHostname
});

View File

@ -52,7 +52,7 @@ module.exports = (server, options) => {
rejectUnauthorized: !wapi_config.insecure
})
.then((response) => {
if (response.body.error === 0 && response.body.data) {
if (parseInt(response.body.error) === 0 && response.body.data) {
wapi_config.password = "You shall not pass";
reply({
'statusCode': 200,
@ -119,7 +119,7 @@ module.exports = (server, options) => {
rejectUnauthorized: !req.payload.insecure
})
.then((response) => {
if (response.body.error === 0 && response.body.data) {
if (parseInt(response.body.error) === 0 && response.body.data) {
needle('get', `${req.payload.url}:${req.payload.port}/agents/000`, {}, {
username: req.payload.user,
password: req.payload.password,

View File

@ -4,7 +4,7 @@ const needle = require('needle');
const colors = require('ansicolors');
const blueWazuh = colors.blue('wazuh');
const OBJECTS_FILE = 'integration_files/objects_file.json';
const OBJECTS_FILE = './integration_files/objects_file.json';
module.exports = (server, options) => {
//const uiSettings = server.uiSettings();
@ -150,11 +150,12 @@ module.exports = (server, options) => {
}
};
let tmpUrl = `http://localhost:${server.info.port}/api/saved_objects/index-pattern'`;
let tmpUrl = `http://localhost:${server.info.port}/api/saved_objects/index-pattern`;
needle('post', tmpUrl, body, options)
.then((resp) => {
server.log([blueWazuh, 'initialize', 'info'], 'Successfully created index-pattern.');
console.log(resp);
// Set the index-pattern as default in the Kibana configuration
setDefaultKibanaSettings(resp.body.id);
// Import objects (dashboards and visualizations) CAREFUL HERE, WE HAVE TO MANAGE SUCESIVE APP INITIATIONS!!!
@ -252,4 +253,4 @@ module.exports = (server, options) => {
// Check Kibana index and if it is prepared, start the initialization of Wazuh App.
checkKibanaIndex();
};
};

View File

@ -121,11 +121,11 @@ module.exports = (server, options) => {
type: 'wazuh-configuration'
})
.then((data) => {
if (data.hits.total == 1) {
if (data.hits.total === 1) {
callback(data.hits);
} else {
callback({
'error': 'no credentials',
'error': 'no credentials',
'error_code': 1
});
}
@ -139,145 +139,152 @@ module.exports = (server, options) => {
};
// fetchAgents on demand
var fetchAgents = function () {
getConfig(loadCredentials);
return;
};
const fetchAgents = () => getConfig(loadCredentials);
// Configure Kibana patterns.
var configureKibana = function () {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Creating index pattern: ' + index_pattern);
const configureKibana = () => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'],
`Creating index pattern: ${index_pattern}`);
// Call the internal API and wait for the response
var options = {
let options = {
headers: {
'kbn-version': packageJSON.kibana.version
},
json: true
}
};
var body = {
let body = {
attributes: {
title: index_pattern,
title: index_pattern,
timeFieldName: '@timestamp'
}
}
};
return needle('post', 'http://localhost:' + server.info.port + '/api/saved_objects/index-pattern', body, options);
};
// Creating wazuh-monitoring index
var createIndex = function (todayIndex) {
elasticRequest.callWithInternalUser('indices.create', {
index: todayIndex
}).then(
function () {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Successfully created today index.');
insertDocument(todayIndex);
},
function () {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'], 'Could not create ' + todayIndex + ' index on elasticsearch.');
}
return needle(
'post',
`http://localhost:${server.info.port}/api/saved_objects/index-pattern`,
body,
options
);
};
// Creating wazuh-monitoring index
const createIndex = (todayIndex) => {
elasticRequest
.callWithInternalUser('indices.create', {
index: todayIndex
})
.then(() => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'],
'Successfully created today index.');
insertDocument(todayIndex);
})
.catch((error) => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'],
`Could not create ${todayIndex} index on elasticsearch.`);
});
};
// Inserting one document per agent into Elastic. Bulk.
var insertDocument = function (todayIndex) {
var body = '';
const insertDocument = (todayIndex) => {
let body = '';
if (agentsArray.length > 0) {
var managerName = agentsArray[0].name;
agentsArray.forEach(function (element) {
let managerName = agentsArray[0].name;
for(let element of agentsArray){
body += '{ "index": { "_index": "' + todayIndex + '", "_type": "wazuh-agent" } }\n';
var date = new Date(Date.now()).toISOString();
let date = new Date(Date.now()).toISOString();
element["@timestamp"] = date;
element["host"] = managerName;
body += JSON.stringify(element) + "\n";
});
if (body == '') {
element["host"] = managerName;
body += JSON.stringify(element) + "\n";
}
if (body === '') {
return;
}
elasticRequest.callWithInternalUser('bulk', {
elasticRequest
.callWithInternalUser('bulk', {
index: todayIndex,
type: 'agent',
body: body
}).then(function (response) {
agentsArray.length = 0;
}, function (err) {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'], 'Error inserting agent data into elasticsearch. Bulk request failed.');
type: 'agent',
body: body
})
.then((response) => agentsArray.length = 0)
.catch((err) => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'],
'Error inserting agent data into elasticsearch. Bulk request failed.');
});
}
};
// Save agent status into elasticsearch, create index and/or insert document
var saveStatus = function () {
fDate = new Date().toISOString().replace(/T/, '-').replace(/\..+/, '').replace(/-/g, '.').replace(/:/g, '').slice(0, -7);
const saveStatus = () => {
fDate = new Date().toISOString().replace(/T/, '-').replace(/\..+/, '').replace(/-/g, '.').replace(/: /g, '').slice(0, -7);
todayIndex = index_prefix + fDate;
elasticRequest.callWithInternalUser('indices.exists', {
elasticRequest
.callWithInternalUser('indices.exists', {
index: todayIndex
}).then(
function (result) {
if (result) {
insertDocument(todayIndex);
} else {
createIndex(todayIndex);
}
},
function () {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'], 'Could not check if the index ' + todayIndex + ' exists.');
})
.then((result) => {
if (result) {
insertDocument(todayIndex);
} else {
createIndex(todayIndex);
}
);
})
.catch((error) => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'],
`Could not check if the index ${todayIndex} exists.`);
});
};
// Main. First execution when installing / loading App.
var init = function () {
const init = () => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Creating today index...');
saveStatus();
elasticRequest.callWithInternalUser('search', {
elasticRequest
.callWithInternalUser('search', {
index: '.kibana',
type: 'doc',
q: 'index-pattern.title:"wazuh-monitoring-*"'
}).then(
function (data) {
if (data.hits.total == 1) {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Skipping index-pattern creation. Already exists.');
} else {
configureKibana();
}
},
function (error) {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'], 'Could not reach elasticsearch.');
type: 'doc',
q: 'index-pattern.title:"wazuh-monitoring-*"'
})
.then((data) => {
if (data.hits.total === 1) {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'],
'Skipping index-pattern creation. Already exists.');
} else {
configureKibana();
}
);
}
})
.catch((error) => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'error'],
'Could not reach elasticsearch.');
});
};
// Wait until Elasticsearch is ready
var checkElasticStatus = function () {
elasticRequest.callWithInternalUser('info').then(
function (data) {
server.plugins.elasticsearch.waitUntilReady().then(function () {
init();
});
},
function (data) {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Waiting for Elasticsearch to be up...');
setTimeout(function () {
checkElasticStatus()
}, 3000)
}
);
}
const checkElasticStatus = () => {
elasticRequest
.callWithInternalUser('info')
.then((data) => server.plugins.elasticsearch.waitUntilReady())
.then(() => init())
.catch((error) => {
server.log([blueWazuh, 'Wazuh agents monitoring', 'info'], 'Waiting for Elasticsearch to be up...');
setTimeout(() => checkElasticStatus(), 3000);
});
};
// Starting
checkElasticStatus();
// Cron tab for getting agent status.
cron.schedule('0 */10 * * * *', function () {
cron.schedule('0 */10 * * * *', () => {
agentsArray.length = 0;
getConfig(loadCredentials);
}, true);
module.exports = fetchAgents;
}
};