Merge branch 'rename' into 3.5-6.3-internet-explorer

This commit is contained in:
JuanjiJG 2018-08-22 14:14:01 +02:00
commit 8bbe0a91e3
75 changed files with 1738 additions and 1377 deletions

View File

@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import * as FileSaver from '../services/file-saver'
import * as FileSaver from '../../services/file-saver'
const app = uiModules.get('app/wazuh', []);
@ -55,7 +55,7 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
errorHandler.info('Your download should begin automatically...', 'CSV')
const currentApi = JSON.parse(appState.getCurrentAPI()).id;
const output = await csvReq.fetch('/agents', currentApi, wzTableFilter.get());
const blob = new Blob([output], {type: 'text/csv'});
const blob = new Blob([output], {type: 'text/csv'}); // eslint-disable-line
FileSaver.saveAs(blob, 'agents.csv');

View File

@ -9,16 +9,22 @@
*
* Find more information about this on the LICENSE file.
*/
import beautifier from '../utils/json-beautifier';
import beautifier from '../../utils/json-beautifier';
import { uiModules } from 'ui/modules';
import FilterHandler from '../utils/filter-handler';
import generateMetric from '../utils/generate-metric';
import TabNames from '../utils/tab-names';
import { metricsAudit, metricsVulnerability, metricsScap, metricsCiscat, metricsVirustotal } from '../utils/agents-metrics';
import * as FileSaver from '../services/file-saver';
import FilterHandler from '../../utils/filter-handler';
import generateMetric from '../../utils/generate-metric';
import TabNames from '../../utils/tab-names';
import * as FileSaver from '../../services/file-saver';
import TabDescription from '../../../server/reporting/tab-description';
import {
metricsAudit,
metricsVulnerability,
metricsScap,
metricsCiscat,
metricsVirustotal } from '../../utils/agents-metrics';
import DataFactory from '../services/data-factory';
import TabDescription from '../../server/reporting/tab-description';
const app = uiModules.get('app/wazuh', []);
@ -31,7 +37,6 @@ function (
reportingService, visFactoryService, csvReq,
wzTableFilter
) {
const agentFactory = new DataFactory(apiReq,'/agents');
$scope.TabDescription = TabDescription;
$rootScope.reportStatus = false;

View File

@ -10,30 +10,80 @@
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import CodeMirror from '../utils/codemirror/lib/codemirror'
import jsonLint from '../utils/codemirror/json-lint'
import CodeMirror from '../../utils/codemirror/lib/codemirror'
import jsonLint from '../../utils/codemirror/json-lint'
import queryString from 'querystring-browser'
import $ from 'jquery'
const app = uiModules.get('app/wazuh', []);
// Logs controller
app.controller('devToolsController', function($scope, apiReq, $window, appState, errorHandler, $document) {
let groups = [];
class DevToolsController {
constructor($scope, apiReq, $window, appState, errorHandler, $document) {
this.$scope = $scope;
this.apiReq = apiReq;
this.$window = $window;
this.appState = appState;
this.errorHandler = errorHandler;
this.$document = $document;
this.groups = [];
this.linesWithClass = [];
this.widgets = [];
}
const apiInputBox = CodeMirror.fromTextArea($document[0].getElementById('api_input'),{
lineNumbers : true,
matchBrackets : true,
mode : { name: "javascript", json: true },
theme : 'ttcn',
foldGutter : true,
styleSelectedText: true,
gutters : ["CodeMirror-foldgutter"]
});
$onInit() {
this.apiInputBox = CodeMirror.fromTextArea(this.$document[0].getElementById('api_input'),{
lineNumbers : true,
matchBrackets : true,
mode : { name: "javascript", json: true },
theme : 'ttcn',
foldGutter : true,
styleSelectedText: true,
gutters : ["CodeMirror-foldgutter"]
});
const analyzeGroups = () => {
this.apiInputBox.on('change',() => {
this.groups = this.analyzeGroups();
const currentState = this.apiInputBox.getValue().toString();
this.appState.setCurrentDevTools(currentState)
const currentGroup = this.calculateWhichGroup();
if(currentGroup){
const hasWidget = this.widgets.filter(item => item.start === currentGroup.start)
if(hasWidget.length) this.apiInputBox.removeLineWidget(hasWidget[0].widget)
setTimeout(() => this.checkJsonParseError(),450)
}
})
this.apiInputBox.on('cursorActivity',() => {
const currentGroup = this.calculateWhichGroup();
this.highlightGroup(currentGroup);
})
this.apiOutputBox = CodeMirror.fromTextArea(this.$document[0].getElementById('api_output'),{
lineNumbers : true,
matchBrackets : true,
mode : { name: "javascript", json: true },
readOnly : true,
lineWrapping : true,
styleActiveLine: true,
theme : 'ttcn',
foldGutter : true,
gutters : ["CodeMirror-foldgutter"]
});
this.$scope.send = firstTime => this.send(firstTime);
this.$scope.help = () => {
this.$window.open('https://documentation.wazuh.com/current/user-manual/api/reference.html');
}
this.init();
this.$scope.send(true);
}
analyzeGroups() {
try{
const currentState = apiInputBox.getValue().toString();
appState.setCurrentDevTools(currentState)
const currentState = this.apiInputBox.getValue().toString();
this.appState.setCurrentDevTools(currentState)
const tmpgroups = [];
const splitted = currentState.split(/[\r\n]+(?=(?:GET|PUT|POST|DELETE)\b)/gm)
@ -44,7 +94,7 @@ app.controller('devToolsController', function($scope, apiReq, $window, appState,
for(let i=0; i < slen; i++){
let tmp = splitted[i].split('\n');
if(Array.isArray(tmp)) tmp = tmp.filter(item => !item.includes('#'))
const cursor = apiInputBox.getSearchCursor(splitted[i],null,{multiline:true})
const cursor = this.apiInputBox.getSearchCursor(splitted[i],null,{multiline:true})
if(cursor.findNext()) start = cursor.from().line
else return [];
@ -94,55 +144,42 @@ app.controller('devToolsController', function($scope, apiReq, $window, appState,
}
}
apiInputBox.on('change',() => {
groups = analyzeGroups();
const currentState = apiInputBox.getValue().toString();
appState.setCurrentDevTools(currentState)
const currentGroup = calculateWhichGroup();
if(currentGroup){
const hasWidget = widgets.filter(item => item.start === currentGroup.start)
if(hasWidget.length) apiInputBox.removeLineWidget(hasWidget[0].widget)
setTimeout(() => checkJsonParseError(),450)
highlightGroup(group) {
for(const line of this.linesWithClass){
this.apiInputBox.removeLineClass(line,'background',"CodeMirror-styled-background")
}
})
let linesWithClass = [], widgets = [];
const highlightGroup = group => {
for(const line of linesWithClass){
apiInputBox.removeLineClass(line,'background',"CodeMirror-styled-background")
}
linesWithClass = [];
this.linesWithClass = [];
if(group) {
if(!group.requestTextJson) {
linesWithClass.push(apiInputBox.addLineClass(group.start,'background',"CodeMirror-styled-background"))
this.linesWithClass.push(this.apiInputBox.addLineClass(group.start,'background',"CodeMirror-styled-background"))
return;
}
for(let i=group.start; i<=group.end; i++){
linesWithClass.push(apiInputBox.addLineClass(i,'background',"CodeMirror-styled-background"))
this.linesWithClass.push(this.apiInputBox.addLineClass(i,'background',"CodeMirror-styled-background"))
}
}
}
const checkJsonParseError = () => {
checkJsonParseError() {
const affectedGroups = [];
for(const widget of widgets){
apiInputBox.removeLineWidget(widget.widget)
for(const widget of this.widgets){
this.apiInputBox.removeLineWidget(widget.widget)
}
widgets = [];
for(const item of groups){
this.widgets = [];
for(const item of this.groups){
if(item.requestTextJson){
try {
jsonLint.parse(item.requestTextJson)
} catch(error) {
affectedGroups.push(item.requestText);
const msg = $document[0].createElement("div");
msg.id = new Date().getTime()/1000;
const icon = msg.appendChild($document[0].createElement("div"));
const msg = this.$document[0].createElement("div");
msg.id = new Date().getTimDevToolsControllere()/1000;
const icon = msg.appendChild(this.$document[0].createElement("div"));
icon.className = "lint-error-icon";
icon.id = new Date().getTime()/1000;
icon.onmouseover = () => {
const advice = msg.appendChild($document[0].createElement("span"));
const advice = msg.appendChild(this.$document[0].createElement("span"));
advice.id = new Date().getTime()/1000;
advice.innerText = error.message || 'Error parsing query'
advice.className = 'lint-block-wz'
@ -152,60 +189,43 @@ app.controller('devToolsController', function($scope, apiReq, $window, appState,
msg.removeChild(msg.lastChild)
}
widgets.push({start:item.start,widget:apiInputBox.addLineWidget(item.start, msg, {coverGutter: false, noHScroll: true})});
this.widgets.push({start:item.start,widget:this.apiInputBox.addLineWidget(item.start, msg, {coverGutter: false, noHScroll: true})});
}
}
}
return affectedGroups;
}
apiInputBox.on('cursorActivity',() => {
const currentGroup = calculateWhichGroup();
highlightGroup(currentGroup);
})
const init = () => {
apiInputBox.setSize('auto','100%')
apiOutputBox.setSize('auto','100%')
const currentState = appState.getCurrentDevTools();
init() {
this.apiInputBox.setSize('auto','100%')
this.apiOutputBox.setSize('auto','100%')
const currentState = this.appState.getCurrentDevTools();
if(!currentState){
const demoStr = 'GET /\n\n# Comment here\nGET /agents\n' + JSON.stringify({limit:1},null,2);
appState.setCurrentDevTools(demoStr);
apiInputBox.getDoc().setValue(demoStr);
this.appState.setCurrentDevTools(demoStr);
this.apiInputBox.getDoc().setValue(demoStr);
} else {
apiInputBox.getDoc().setValue(currentState)
this.apiInputBox.getDoc().setValue(currentState)
}
groups = analyzeGroups();
const currentGroup = calculateWhichGroup();
highlightGroup(currentGroup);
this.groups = this.analyzeGroups();
const currentGroup = this.calculateWhichGroup();
this.highlightGroup(currentGroup);
}
const apiOutputBox = CodeMirror.fromTextArea($document[0].getElementById('api_output'),{
lineNumbers : true,
matchBrackets : true,
mode : { name: "javascript", json: true },
readOnly : true,
lineWrapping : true,
styleActiveLine: true,
theme : 'ttcn',
foldGutter : true,
gutters : ["CodeMirror-foldgutter"]
});
const calculateWhichGroup = firstTime => {
calculateWhichGroup(firstTime) {
try {
const selection = apiInputBox.getCursor()
const selection = this.apiInputBox.getCursor()
const desiredGroup = firstTime ?
groups.filter(item => item.requestText) :
groups.filter(item => item.requestText && (item.end >= selection.line && item.start <= selection.line));
this.groups.filter(item => item.requestText) :
this.groups.filter(item => item.requestText && (item.end >= selection.line && item.start <= selection.line));
// Place play button at first line from the selected group
const cords = apiInputBox.cursorCoords({line:desiredGroup[0].start,ch:0});
const cords = this.apiInputBox.cursorCoords({line:desiredGroup[0].start,ch:0});
if(!$('#play_button').is(":visible")) $('#play_button').show()
const currentPlayButton = $('#play_button').offset();
$('#play_button').offset({top:cords.top,left:currentPlayButton.left})
if(firstTime) highlightGroup(desiredGroup[0])
if(firstTime) this.highlightGroup(desiredGroup[0])
return desiredGroup[0];
} catch(error) {
$('#play_button').hide()
@ -214,22 +234,22 @@ app.controller('devToolsController', function($scope, apiReq, $window, appState,
}
$scope.send = async firstTime => {
async send(firstTime) {
try {
groups = analyzeGroups();
this.groups = this.analyzeGroups();
const desiredGroup = calculateWhichGroup(firstTime);
const desiredGroup = this.calculateWhichGroup(firstTime);
if(desiredGroup) {
if(firstTime){
const cords = apiInputBox.cursorCoords({line:desiredGroup.start,ch:0});
const cords = this.apiInputBox.cursorCoords({line:desiredGroup.start,ch:0});
const currentPlayButton = $('#play_button').offset();
$('#play_button').offset({top:cords.top+10,left:currentPlayButton.left})
}
const affectedGroups = checkJsonParseError();
const affectedGroups = this.checkJsonParseError();
const filteredAffectedGroups = affectedGroups.filter(item => item === desiredGroup.requestText);
if(filteredAffectedGroups.length) {apiOutputBox.setValue('Error parsing JSON query'); return;}
if(filteredAffectedGroups.length) {this.apiOutputBox.setValue('Error parsing JSON query'); return;}
const method = desiredGroup.requestText.startsWith('GET') ?
'GET' :
@ -274,34 +294,29 @@ app.controller('devToolsController', function($scope, apiReq, $window, appState,
const path = req.includes('?') ? req.split('?')[0] : req;
if(typeof JSONraw === 'object') JSONraw.devTools = true;
const output = await apiReq.request(method, path, JSONraw)
const output = await this.apiReq.request(method, path, JSONraw)
apiOutputBox.setValue(
this.apiOutputBox.setValue(
JSON.stringify(output.data.data,null,2)
)
} else {
apiOutputBox.setValue('Welcome!')
this.apiOutputBox.setValue('Welcome!')
}
} catch(error) {
const parsedError = errorHandler.handle(error,null,null,true);
const parsedError = this.errorHandler.handle(error,null,null,true);
if(typeof parsedError === 'string') {
return apiOutputBox.setValue(parsedError);
return this.apiOutputBox.setValue(parsedError);
} else if(error && error.data && typeof error.data === 'object') {
return apiOutputBox.setValue(JSON.stringify(error.data))
return this.apiOutputBox.setValue(JSON.stringify(error.data))
} else {
return apiOutputBox.setValue('Empty')
return this.apiOutputBox.setValue('Empty')
}
}
}
}
$scope.help = () => {
$window.open('https://documentation.wazuh.com/current/user-manual/api/reference.html');
}
init();
$scope.send(true);
});
// Logs controller
app.controller('devToolsController', DevToolsController);

View File

@ -9,16 +9,11 @@
*
* Find more information about this on the LICENSE file.
*/
import './blank-screen-controller'
import './overview'
import './manager'
import './ruleset'
import './osseclog'
import './groups'
import './agents'
import './agents-preview'
import './management'
import './agent/agents-preview'
import './agent/agents'
import './settings'
import './health-check'
import './dev-tools'
import './monitoring'
import './reporting'
import './misc'

View File

@ -0,0 +1,126 @@
/*
* Wazuh app - Management configuration controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules';
import beautifier from '../../utils/json-beautifier';
import js2xmlparser from 'js2xmlparser';
import XMLBeautifier from '../../utils/xml-beautifier';
import angular from 'angular';
const app = uiModules.get('app/wazuh', []);
class ConfigurationController {
constructor($scope, errorHandler, apiReq) {
this.$scope = $scope;
this.errorHandler = errorHandler;
this.apiReq = apiReq;
this.$scope.load = true;
this.$scope.isArray = Array.isArray;
this.configRaw = {};
this.$scope.switchItem = item => this.switchItem(item);
this.$scope.getXML = name => this.getXML(name);
this.$scope.getJSON = name => this.getJSON(name);
}
/**
* Initialize
*/
$onInit() {
this.load();
}
/**
* Switchs between configuration sections
* @param {*} item
*/
switchItem(item) {
this.$scope.XMLContent = false;
this.$scope.JSONContent = false;
this.$scope.selectedItem = item;
if(!this.$scope.$$phase) this.$scope.$digest();
}
/**
* Assigns XML raw content for specific configuration
* @param {string} name Name of the configuration section
*/
getXML(name) {
this.$scope.JSONContent = false;
if(this.$scope.XMLContent){
this.$scope.XMLContent = false;
} else {
try {
this.$scope.XMLContent = XMLBeautifier(js2xmlparser.parse(name, this.configRaw[name]));
} catch (error) { this.$scope.XMLContent = false; }
}
if(!this.$scope.$$phase) this.$scope.$digest();
}
/**
* Assigns JSON raw content for specific configuration
* @param {string} name Name of the configuration section
*/
getJSON(name) {
this.$scope.XMLContent = false;
if(this.$scope.JSONContent){
this.$scope.JSONContent = false;
} else {
try {
this.$scope.JSONContent = beautifier.prettyPrint(this.configRaw[name]);
} catch (error) { this.$scope.JSONContent = false; }
}
if(!this.$scope.$$phase) this.$scope.$digest();
}
/**
* Fetchs required data
*/
async load() {
try{
const data = await this.apiReq.request('GET', '/manager/configuration', {});
Object.assign(this.configRaw, angular.copy(data.data.data))
this.$scope.managerConfiguration = data.data.data;
if(this.$scope.managerConfiguration && this.$scope.managerConfiguration['active-response']){
for(const ar of this.$scope.managerConfiguration['active-response']) {
const rulesArray = ar.rules_id ?
ar.rules_id.split(',') :
[];
if(ar.rules_id && rulesArray.length > 1){
const tmp = [];
for(const id of rulesArray){
const rule = await this.apiReq.request('GET',`/rules/${id}`,{});
tmp.push(rule.data.data.items[0]);
}
ar.rules = tmp;
} else if(ar.rules_id){
const rule = await this.apiReq.request('GET',`/rules/${ar.rules_id}`,{});
ar.rule = rule.data.data.items[0];
}
}
}
this.$scope.raw = beautifier.prettyPrint(data.data.data);
this.$scope.load = false;
if(!this.$scope.$$phase) this.$scope.$digest();
return;
} catch (error) {
this.errorHandler.handle(error,'Manager');
}
return;
}
}
app.controller('managerConfigurationController', ConfigurationController);

View File

@ -0,0 +1,141 @@
/*
* Wazuh app - Ruleset controllers
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import * as FileSaver from '../../services/file-saver'
const colors = [
'#004A65', '#00665F', '#BF4B45', '#BF9037', '#1D8C2E', 'BB3ABF',
'#00B1F1', '#00F2E2', '#7F322E', '#7F6025', '#104C19', '7C267F',
'#0079A5', '#00A69B', '#FF645C', '#FFC04A', '#2ACC43', 'F94DFF',
'#0082B2', '#00B3A7', '#401917', '#403012', '#2DD947', '3E1340',
'#00668B', '#008C83', '#E55A53', '#E5AD43', '#25B23B', 'E045E5'
];
const app = uiModules.get('app/wazuh', []);
app.controller('decodersController', function ($scope, $rootScope, $sce, errorHandler, appState, csvReq, wzTableFilter) {
$scope.setRulesTab = tab => $rootScope.globalRulesetTab = tab;
$scope.appliedFilters = [];
//Initialization
$scope.searchTerm = '';
$scope.viewingDetail = false;
$scope.typeFilter = "all";
$scope.setRulesTab('decoders');
$scope.isArray = Array.isArray;
$scope.includesFilter = filterName => $scope.appliedFilters.map(item => item.name).includes(filterName);
$scope.getFilter = filterName => {
const filtered = $scope.appliedFilters.filter(item => item.name === filterName);
return filtered.length ? filtered[0].value : '';
}
$scope.removeFilter = filterName => {
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== filterName);
return $scope.$broadcast('wazuhRemoveFilter',{filterName});
}
$scope.colorRegex = regex => {
regex = regex.toString();
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 = order => {
order = order.toString();
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);
};
// Reloading event listener
$scope.$on('rulesetIsReloaded',() => {
$scope.viewingDetail = false;
if(!$scope.$$phase) $scope.$digest();
});
$scope.search = term => {
if(term && term.startsWith('path:') && term.split('path:')[1].trim()) {
$scope.custom_search = ''
const filter = {name:'path',value:term.split('path:')[1].trim()};
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== 'path');
$scope.appliedFilters.push(filter)
$scope.$broadcast('wazuhFilter',{filter})
} else if(term && term.startsWith('file:') && term.split('file:')[1].trim()) {
$scope.custom_search = ''
const filter = {name:'file',value:term.split('file:')[1].trim()};
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== 'file');
$scope.appliedFilters.push(filter)
$scope.$broadcast('wazuhFilter',{filter})
} else {
$scope.$broadcast('wazuhSearch',{term,removeFilters: true})
}
}
$scope.onlyParents = typeFilter => {
$scope.appliedFilters = [];
if(typeFilter === 'all') $scope.$broadcast('wazuhUpdateInstancePath',{path:'/decoders'})
else $scope.$broadcast('wazuhUpdateInstancePath',{path:'/decoders/parents'})
}
$scope.downloadCsv = async () => {
try {
const currentApi = JSON.parse(appState.getCurrentAPI()).id;
const output = await csvReq.fetch('/decoders', currentApi, wzTableFilter.get());
const blob = new Blob([output], {type: 'text/csv'}); // eslint-disable-line
FileSaver.saveAs(blob, 'decoders.csv');
return;
} catch (error) {
errorHandler.handle(error,'Download CSV');
}
return;
}
/**
* This function takes back to the list but adding a filter from the detail view
*/
$scope.addDetailFilter = (name, value) => {
$scope.appliedFilters.push({name,value})
// Clear the autocomplete component
$scope.searchTerm = '';
// Go back to the list
$scope.closeDetailView();
}
$scope.$on('wazuhShowDecoder',(event,parameters) => {
$scope.currentDecoder = parameters.decoder;
$scope.viewingDetail = true;
if(!$scope.$$phase) $scope.$digest();
})
/**
* This function changes to the decoders list view
*/
$scope.closeDetailView = clear => {
if(clear) $scope.appliedFilters = $scope.appliedFilters.slice(0,$scope.appliedFilters.length-1);
$scope.viewingDetail = false;
$scope.currentDecoder = false;
if(!$scope.$$phase) $scope.$digest();
}
});

View File

@ -1,5 +1,5 @@
/*
* Wazuh app - Groups controller
* Wazuh app - Management groups controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
@ -9,9 +9,9 @@
*
* Find more information about this on the LICENSE file.
*/
import beautifier from '../utils/json-beautifier';
import beautifier from '../../utils/json-beautifier';
import { uiModules } from 'ui/modules'
import * as FileSaver from '../services/file-saver'
import * as FileSaver from '../../services/file-saver'
const app = uiModules.get('app/wazuh', []);

View File

@ -0,0 +1,19 @@
/*
* Wazuh app - File for app requirements and set up
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import './management'
import './configuration'
import './status'
import './logs'
import './groups'
import './rules'
import './decoders'
import './monitoring'

View File

@ -0,0 +1,109 @@
/*
* Wazuh app - Management logs controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import * as FileSaver from '../../services/file-saver'
const app = uiModules.get('app/wazuh', []);
class Logs {
constructor($scope, apiReq, errorHandler, csvReq, appState, wzTableFilter) {
this.$scope = $scope;
this.apiReq = apiReq;
this.errorHandler = errorHandler;
this.csvReq = csvReq;
this.appState = appState;
this.wzTableFilter = wzTableFilter;
this.$scope.type_log = 'all';
this.$scope.category = 'all';
}
/**
* Initialize
*/
$onInit() {
this.initialize();
this.$scope.search = term => this.search(term);
this.$scope.filter = filter => this.filter(filter);
this.$scope.playRealtime = () => this.playRealtime();
this.$scope.stopRealtime = () => this.stopRealtime();
this.$scope.downloadCsv = () => this.downloadCsv();
}
/**
* Event handler for the search bar.
* @param {string} term Term(s) to be searched
*/
search(term) {
this.$scope.$broadcast('wazuhSearch',{term})
}
/**
* Event handler for the selectors
* @param {*} filter Filter to be applied
*/
filter(filter) {
this.$scope.$broadcast('wazuhFilter',{filter})
}
/**
* Starts real time mode
*/
playRealtime() {
this.$scope.realtime = true;
this.$scope.$broadcast('wazuhPlayRealTime')
}
/**
* Stops real time mode
*/
stopRealtime() {
this.$scope.realtime = false;
this.$scope.$broadcast('wazuhStopRealTime')
}
/**
* Builds a CSV file from the table and starts the download
*/
async downloadCsv() {
try {
this.errorHandler.info('Your download should begin automatically...', 'CSV')
const currentApi = JSON.parse(this.appState.getCurrentAPI()).id;
const output = await this.csvReq.fetch('/manager/logs', currentApi, this.wzTableFilter.get());
const blob = new Blob([output], {type: 'text/csv'}); // eslint-disable-line
FileSaver.saveAs(blob, 'logs.csv');
return;
} catch (error) {
this.errorHandler.handle(error,'Download CSV');
}
return;
}
/**
* Fetchs required data
*/
async initialize() {
try{
const data = await this.apiReq.request('GET', '/manager/logs/summary', {});
const daemons = data.data.data;
this.$scope.daemons = Object.keys(daemons).map(item => { return { title: item } })
if(!this.$scope.$$phase) this.$scope.$digest();
return;
} catch (error) {
this.errorHandler.handle(error,'Logs');
}
return;
}
}
// Logs controller
app.controller('managerLogController', Logs);

View File

@ -0,0 +1,81 @@
/*
* Wazuh app - Management controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules';
import TabNames from '../../utils/tab-names';
const app = uiModules.get('app/wazuh', []);
class Management {
constructor($scope, $rootScope, $routeParams, $location) {
this.$scope = $scope;
this.$rootScope = $rootScope;
this.$routeParams = $routeParams;
this.$location = $location;
this.$scope.tab = 'welcome';
this.$scope.rulesetTab = 'rules';
this.$scope.tabNames = TabNames;
this.$scope.wazuhManagementTabs = ['ruleset', 'groups', 'configuration'];
this.$scope.statusReportsTabs = ['status', 'logs', 'monitoring', 'reporting'];
}
$onInit() {
if (this.$routeParams.tab){
this.$scope.tab = this.$routeParams.tab;
}
this.$scope.reloadGroups = () => this.reloadGroups();
this.$scope.reloadRuleset = () => this.reloadRuleset();
this.$scope.inArray = (item, array) => this.inArray(item,array);
this.$scope.switchTab = tab => this.switchTab(tab);
this.$scope.setRulesTab = tab => this.setRulesTab(tab);
this.$scope.$watch('tab',() => this.watchTab());
}
reloadGroups() {
this.$scope.tab = 'groups';
this.$scope.$broadcast('groupsIsReloaded')
}
reloadRuleset() {
this.$scope.tab = 'ruleset';
this.$scope.$broadcast('rulesetIsReloaded')
}
inArray(item, array) {
return item && Array.isArray(array) && array.includes(item);
}
switchTab(tab) {
this.$scope.tab = tab;
}
setRulesTab(tab) {
this.$scope.rulesetTab = tab;
}
watchTab() {
if(this.$scope.tab === 'ruleset') {
this.$rootScope.globalRuleSet = 'ruleset';
this.$rootScope.globalRulesetTab = this.$scope.rulesetTab;
} else {
delete this.$rootScope.globalRuleSet;
delete this.$rootScope.globalRulesetTab;
}
this.$location.search('tab', this.$scope.tab);
}
}
app.controller('managementController', Management);

View File

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

View File

@ -10,7 +10,7 @@
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import * as FileSaver from '../services/file-saver'
import * as FileSaver from '../../services/file-saver'
const colors = [
'#004A65', '#00665F', '#BF4B45', '#BF9037', '#1D8C2E', 'BB3ABF',
@ -148,122 +148,4 @@ app.controller('rulesController', function ($scope, $rootScope, $sce, errorHandl
if(!$scope.$$phase) $scope.$digest();
}
});
app.controller('decodersController', function ($scope, $rootScope, $sce, errorHandler, appState, csvReq, wzTableFilter) {
$scope.setRulesTab = tab => $rootScope.globalRulesetTab = tab;
$scope.appliedFilters = [];
//Initialization
$scope.searchTerm = '';
$scope.viewingDetail = false;
$scope.typeFilter = "all";
$scope.setRulesTab('decoders');
$scope.isArray = Array.isArray;
$scope.includesFilter = filterName => $scope.appliedFilters.map(item => item.name).includes(filterName);
$scope.getFilter = filterName => {
const filtered = $scope.appliedFilters.filter(item => item.name === filterName);
return filtered.length ? filtered[0].value : '';
}
$scope.removeFilter = filterName => {
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== filterName);
return $scope.$broadcast('wazuhRemoveFilter',{filterName});
}
$scope.colorRegex = regex => {
regex = regex.toString();
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 = order => {
order = order.toString();
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);
};
// Reloading event listener
$scope.$on('rulesetIsReloaded',() => {
$scope.viewingDetail = false;
if(!$scope.$$phase) $scope.$digest();
});
$scope.search = term => {
if(term && term.startsWith('path:') && term.split('path:')[1].trim()) {
$scope.custom_search = ''
const filter = {name:'path',value:term.split('path:')[1].trim()};
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== 'path');
$scope.appliedFilters.push(filter)
$scope.$broadcast('wazuhFilter',{filter})
} else if(term && term.startsWith('file:') && term.split('file:')[1].trim()) {
$scope.custom_search = ''
const filter = {name:'file',value:term.split('file:')[1].trim()};
$scope.appliedFilters = $scope.appliedFilters.filter(item => item.name !== 'file');
$scope.appliedFilters.push(filter)
$scope.$broadcast('wazuhFilter',{filter})
} else {
$scope.$broadcast('wazuhSearch',{term,removeFilters: true})
}
}
$scope.onlyParents = typeFilter => {
$scope.appliedFilters = [];
if(typeFilter === 'all') $scope.$broadcast('wazuhUpdateInstancePath',{path:'/decoders'})
else $scope.$broadcast('wazuhUpdateInstancePath',{path:'/decoders/parents'})
}
$scope.downloadCsv = async () => {
try {
const currentApi = JSON.parse(appState.getCurrentAPI()).id;
const output = await csvReq.fetch('/decoders', currentApi, wzTableFilter.get());
const blob = new Blob([output], {type: 'text/csv'}); // eslint-disable-line
FileSaver.saveAs(blob, 'decoders.csv');
return;
} catch (error) {
errorHandler.handle(error,'Download CSV');
}
return;
}
/**
* This function takes back to the list but adding a filter from the detail view
*/
$scope.addDetailFilter = (name, value) => {
$scope.appliedFilters.push({name,value})
// Clear the autocomplete component
$scope.searchTerm = '';
// Go back to the list
$scope.closeDetailView();
}
$scope.$on('wazuhShowDecoder',(event,parameters) => {
$scope.currentDecoder = parameters.decoder;
$scope.viewingDetail = true;
if(!$scope.$$phase) $scope.$digest();
})
/**
* This function changes to the decoders list view
*/
$scope.closeDetailView = clear => {
if(clear) $scope.appliedFilters = $scope.appliedFilters.slice(0,$scope.appliedFilters.length-1);
$scope.viewingDetail = false;
$scope.currentDecoder = false;
if(!$scope.$$phase) $scope.$digest();
}
});
});

View File

@ -0,0 +1,84 @@
/*
* Wazuh app - Management status controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
class StatusController {
constructor($scope, errorHandler, apiReq){
this.$scope = $scope;
this.errorHandler = errorHandler;
this.apiReq = apiReq;
this.$scope.load = true;
this.$scope.getDaemonStatusClass = daemonStatus => this.getDaemonStatusClass(daemonStatus);
}
/**
* Initialize
*/
$onInit() {
return this.init();
}
/**
* Used to show green/red depending on daemon status
* @param {*} daemonStatus
*/
getDaemonStatusClass(daemonStatus) {
return (daemonStatus === 'running') ? 'status teal' : 'status red';
}
/**
* Fetchs all required data
*/
async init() {
try {
const data = await Promise.all([
this.apiReq.request('GET', '/agents/summary', {}),
this.apiReq.request('GET', '/manager/status', {}),
this.apiReq.request('GET', '/manager/info', {}),
this.apiReq.request('GET', '/rules', { offset: 0, limit: 1 }),
this.apiReq.request('GET', '/decoders', { offset: 0, limit: 1 })
])
// Once Wazuh core fixes agent 000 issues, this should be adjusted
const active = data[0].data.data.Active - 1;
const total = data[0].data.data.Total - 1;
this.$scope.agentsCountActive = active;
this.$scope.agentsCountDisconnected = data[0].data.data.Disconnected;
this.$scope.agentsCountNeverConnected = data[0].data.data['Never connected'];
this.$scope.agentsCountTotal = total;
this.$scope.agentsCoverity = (active / total) * 100;
this.$scope.daemons = data[1].data.data;
this.$scope.managerInfo = data[2].data.data;
this.$scope.totalRules = data[3].data.data.totalItems;
this.$scope.totalDecoders = data[4].data.data.totalItems;
const lastAgent = await this.apiReq.request('GET', '/agents', { limit: 1, sort: '-dateAdd' });
const agentInfo = await this.apiReq.request('GET', `/agents/${lastAgent.data.data.items[0].id}`, {});
this.$scope.agentInfo = agentInfo.data.data;
this.$scope.load = false;
if(!this.$scope.$$phase) this.$scope.$digest();
return;
} catch (error) {
return this.errorHandler.handle(error,'Manager');
}
}
}
app.controller('managerStatusController', StatusController);

View File

@ -1,193 +0,0 @@
/*
* Wazuh app - Manager controllers
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules';
import beautifier from '../utils/json-beautifier';
import TabNames from '../utils/tab-names';
import js2xmlparser from 'js2xmlparser';
import XMLBeautifier from '../utils/xml-beautifier';
const app = uiModules.get('app/wazuh', []);
app.controller('managerController', function ($scope, $rootScope, $routeParams, $location) {
$scope.tab = 'welcome';
$scope.rulesetTab = 'rules';
// Tab names
$scope.tabNames = TabNames;
if ($routeParams.tab){
$scope.tab = $routeParams.tab;
}
$scope.reloadGroups = () => {
$scope.tab = 'groups';
$scope.$broadcast('groupsIsReloaded')
}
$scope.reloadRuleset = () => {
$scope.tab = 'ruleset';
$scope.$broadcast('rulesetIsReloaded')
}
$scope.wazuhManagementTabs = ['ruleset', 'groups', 'configuration'];
$scope.statusReportsTabs = ['status', 'logs', 'monitoring', 'reporting'];
$scope.inArray = (item, array) => item && Array.isArray(array) && array.includes(item);
// Watchers
$scope.$watch('tab', () => {
if($scope.tab === 'ruleset') {
$rootScope.globalRuleSet = 'ruleset';
$rootScope.globalRulesetTab = $scope.rulesetTab;
} else {
delete $rootScope.globalRuleSet;
delete $rootScope.globalRulesetTab;
}
$location.search('tab', $scope.tab);
});
$scope.switchTab = tab => {
$scope.tab = tab;
}
$scope.setRulesTab = (tab) => $scope.rulesetTab = tab;
$scope.$on("$destroy", () => {
});
});
app.controller('managerStatusController', function ($scope, errorHandler, apiReq) {
//Initialization
$scope.load = true;
//Functions
$scope.getDaemonStatusClass = daemonStatus => (daemonStatus === 'running') ? 'status teal' : 'status red';
Promise.all([
apiReq.request('GET', '/agents/summary', {}),
apiReq.request('GET', '/manager/status', {}),
apiReq.request('GET', '/manager/info', {}),
apiReq.request('GET', '/rules', { offset: 0, limit: 1 }),
apiReq.request('GET', '/decoders', { offset: 0, limit: 1 })
])
.then(data => {
// Once Wazuh core fixes agent 000 issues, this should be adjusted
const active = data[0].data.data.Active - 1;
const total = data[0].data.data.Total - 1;
$scope.agentsCountActive = active;
$scope.agentsCountDisconnected = data[0].data.data.Disconnected;
$scope.agentsCountNeverConnected = data[0].data.data['Never connected'];
$scope.agentsCountTotal = total;
$scope.agentsCoverity = (active / total) * 100;
$scope.daemons = data[1].data.data;
$scope.managerInfo = data[2].data.data;
$scope.totalRules = data[3].data.data.totalItems;
$scope.totalDecoders = data[4].data.data.totalItems;
return apiReq.request('GET', '/agents', { limit: 1, sort: '-dateAdd' });
})
.then(lastAgent => apiReq.request('GET', `/agents/${lastAgent.data.data.items[0].id}`, {}))
.then(agentInfo => {
$scope.agentInfo = agentInfo.data.data;
$scope.load = false;
if(!$scope.$$phase) $scope.$digest();
})
.catch(error => errorHandler.handle(error,'Manager'));
$scope.$on("$destroy", () => {
});
});
app.controller('managerConfigurationController', function ($scope, errorHandler, apiReq) {
//Initialization
$scope.load = true;
$scope.isArray = Array.isArray;
$scope.switchItem = item => {
$scope.XMLContent = false;
$scope.JSONContent = false;
$scope.selectedItem = item;
if(!$scope.$$phase) $scope.$digest();
}
$scope.getXML = name => {
$scope.JSONContent = false;
if($scope.XMLContent){
$scope.XMLContent = false;
} else {
try {
$scope.XMLContent = XMLBeautifier(js2xmlparser.parse(name,configRaw[name]));
} catch (error) { $scope.XMLContent = false; }
}
if(!$scope.$$phase) $scope.$digest();
}
$scope.getJSON = name => {
$scope.XMLContent = false;
if($scope.JSONContent){
$scope.JSONContent = false;
} else {
try {
$scope.JSONContent = beautifier.prettyPrint(configRaw[name]);
} catch (error) { $scope.JSONContent = false; }
}
if(!$scope.$$phase) $scope.$digest();
}
const configRaw = {};
//Functions
const load = async () => {
try{
const data = await apiReq.request('GET', '/manager/configuration', {});
Object.assign(configRaw,angular.copy(data.data.data))
$scope.managerConfiguration = data.data.data;
if($scope.managerConfiguration && $scope.managerConfiguration['active-response']){
for(const ar of $scope.managerConfiguration['active-response']) {
const rulesArray = ar.rules_id ?
ar.rules_id.split(',') :
[];
if(ar.rules_id && rulesArray.length > 1){
const tmp = [];
for(const id of rulesArray){
const rule = await apiReq.request('GET',`/rules/${id}`,{});
tmp.push(rule.data.data.items[0]);
}
ar.rules = tmp;
} else if(ar.rules_id){
const rule = await apiReq.request('GET',`/rules/${ar.rules_id}`,{});
ar.rule = rule.data.data.items[0];
}
}
}
$scope.raw = beautifier.prettyPrint(data.data.data);
$scope.load = false;
if(!$scope.$$phase) $scope.$digest();
return;
} catch (error) {
errorHandler.handle(error,'Manager');
}
return;
};
load();
$scope.$on("$destroy", () => {
});
});

View File

@ -13,17 +13,14 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
// Logs controller
app.controller('blankScreenController', function($scope, $location, errorHandler, wzMisc) {
const bse_error = wzMisc.getValue('blankScreenError')
if (bse_error) {
const catchedError = wzMisc.getBlankScr()
if (catchedError) {
let parsed = null;
try {
parsed = errorHandler.handle(bse_error,'',false,true);
} catch (error) {
// Do nothing (intended)
}
$scope.errorToShow = parsed ? parsed : bse_error;
parsed = errorHandler.handle(catchedError,'',false,true);
} catch (error) { } // eslint-disable-line
$scope.errorToShow = parsed || catchedError;
wzMisc.setBlankScr(false)
if (!$scope.$$phase) $scope.$digest();
}

View File

@ -72,7 +72,7 @@ function ($scope, $rootScope, $timeout, $location,
const checkApiConnection = async () => {
try {
if(checks.api) {
const data = await testAPI.check_stored(JSON.parse(appState.getCurrentAPI()).id);
const data = await testAPI.checkStored(JSON.parse(appState.getCurrentAPI()).id);
if(data && data.data && data.data.idChanged) {
const apiRaw = JSON.parse(appState.getCurrentAPI());
appState.setCurrentAPI(JSON.stringify({name: apiRaw.name, id: data.data.idChanged }));

View File

@ -0,0 +1,14 @@
/*
* Wazuh app - File for app requirements and set up
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import './blank-screen-controller'
import './health-check'
import './reporting'

View File

@ -1,71 +0,0 @@
/*
* Wazuh app - Manager logs controller
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import * as FileSaver from '../services/file-saver'
const app = uiModules.get('app/wazuh', []);
// Logs controller
app.controller('managerLogController', function ($scope, apiReq, errorHandler, csvReq, appState, wzTableFilter) {
$scope.type_log = 'all';
$scope.category = 'all';
$scope.search = term => {
$scope.$broadcast('wazuhSearch',{term})
}
$scope.filter = async filter => {
$scope.$broadcast('wazuhFilter',{filter})
}
$scope.playRealtime = () => {
$scope.realtime = true;
$scope.$broadcast('wazuhPlayRealTime')
};
$scope.stopRealtime = () => {
$scope.realtime = false;
$scope.$broadcast('wazuhStopRealTime')
}
$scope.downloadCsv = async () => {
try {
errorHandler.info('Your download should begin automatically...', 'CSV')
const currentApi = JSON.parse(appState.getCurrentAPI()).id;
const output = await csvReq.fetch('/manager/logs', currentApi, wzTableFilter.get());
const blob = new Blob([output], {type: 'text/csv'}); // eslint-disable-line
FileSaver.saveAs(blob, 'logs.csv');
return;
} catch (error) {
errorHandler.handle(error,'Download CSV');
}
return;
}
const initialize = async () => {
try{
const data = await apiReq.request('GET', '/manager/logs/summary', {});
const daemons = data.data.data;
$scope.daemons = Object.keys(daemons).map(item => { return { title: item } })
if(!$scope.$$phase) $scope.$digest();
return;
} catch (error) {
errorHandler.handle(error,'Logs');
}
return;
}
initialize();
});

View File

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

View File

@ -9,20 +9,20 @@
*
* Find more information about this on the LICENSE file.
*/
import base64 from '../utils/base64.js';
import base64 from '../../utils/base64';
import { uiModules } from 'ui/modules';
import TabNames from '../utils/tab-names';
import TabNames from '../../utils/tab-names';
const app = uiModules.get('app/wazuh', []);
app.controller('settingsController',
function ($scope, $routeParams, $window, $location, testAPI, appState, genericReq, errorHandler, wzMisc, wazuhConfig) {
if (wzMisc.getValue('comeFromWizard')) {
if (wzMisc.getWizard()) {
$window.sessionStorage.removeItem('healthCheck');
wzMisc.setWizard(false);
}
$scope.apiIsDown = wzMisc.getValue('apiIsDown');
$scope.apiIsDown = wzMisc.getApiIsDown();
// Initialize
let currentApiEntryIndex;

View File

@ -13,136 +13,140 @@
import menuTemplate from './wz-menu.html'
import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);;
const app = uiModules.get('app/wazuh', []);
app.directive('wzMenu',function(){
return {
controller: function ($scope, $window, $rootScope, appState, patternHandler, courier, errorHandler, genericReq, $location, wzMisc, wazuhConfig) {
class WzMenu {
constructor() {
this.template = menuTemplate;
}
$rootScope.showSelector = appState.getPatternSelector();
controller($scope, $window, $rootScope, appState, patternHandler, courier, errorHandler, genericReq, $location, wzMisc, wazuhConfig) {
if(!$rootScope.$$phase) $rootScope.$digest();
$rootScope.showSelector = appState.getPatternSelector();
if(appState.getCurrentAPI()) {
$scope.theresAPI = true;
$scope.currentAPI = JSON.parse(appState.getCurrentAPI()).name;
if(!$rootScope.$$phase) $rootScope.$digest();
if(appState.getCurrentAPI()) {
$scope.theresAPI = true;
$scope.currentAPI = JSON.parse(appState.getCurrentAPI()).name;
}
else {
$scope.theresAPI = false;
}
$scope.goToClick = path => {
$window.location.href = path;
}
const load = async () => {
try {
// Get the configuration to check if pattern selector is enabled
const config = wazuhConfig.getConfig();
appState.setPatternSelector(config['ip.selector']);
// Abort if we have disabled the pattern selector
if(!appState.getPatternSelector()) return;
// Show the pattern selector
$rootScope.showSelector = true;
let filtered = false;
// If there is no current pattern, fetch it
if(!appState.getCurrentPattern()) {
const currentPattern = await genericReq.request('GET', '/get-list');
if(!currentPattern.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
appState.setCurrentPattern(currentPattern.data.data[0].id);
} else {
// If there is current pattern, check if there is some pattern
const patternList = await genericReq.request('GET', '/get-list');
if(!patternList.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
// Check if the current pattern cookie is valid
filtered = patternList.data.data.filter(item => item.id.includes(appState.getCurrentPattern()))
if(!filtered.length) appState.setCurrentPattern(patternList.data.data[0].id)
}
const data = filtered ? filtered : await courier.indexPatterns.get(appState.getCurrentPattern());
$scope.theresPattern = true;
$scope.currentPattern = data.title;
const list = await patternHandler.getPatternList();
// Getting the list of index patterns
if(list) {
$scope.patternList = list;
$scope.currentSelectedPattern = appState.getCurrentPattern();
}
if(!$scope.$$phase) $scope.$digest();
if(!$rootScope.$$phase) $rootScope.$digest();
return;
} catch (error) {
errorHandler.handle(error,'Directives - Menu');
$scope.theresPattern = false;
}
else {
}
load();
// Function to change the current index pattern on the app
$scope.changePattern = async selectedPattern => {
try{
if(!appState.getPatternSelector()) return;
$scope.currentSelectedPattern = await patternHandler.changePattern(selectedPattern);
if(!$scope.$$phase) $scope.$digest();
$window.location.reload();
return;
}catch(error){
errorHandler.handle(error,'Directives - Menu');
}
}
$scope.$on('updateAPI', (evt,params) => {
const current = appState.getCurrentAPI();
if(current) {
const parsed = JSON.parse(current);
// If we've received cluster info as parameter, it means we must update our stored cookie
if(params && params.cluster_info){
if(params.cluster_info.status === 'enabled'){
parsed.name = params.cluster_info.cluster;
} else {
parsed.name = params.cluster_info.manager;
}
appState.setCurrentAPI(JSON.stringify(parsed));
}
$scope.theresAPI = true;
$scope.currentAPI = parsed.name;
} else {
$scope.theresAPI = false;
}
});
$scope.goToClick = path => {
$window.location.href = path;
}
const load = async () => {
try {
// Get the configuration to check if pattern selector is enabled
const config = wazuhConfig.getConfig();
appState.setPatternSelector(config['ip.selector']);
// Abort if we have disabled the pattern selector
if(!appState.getPatternSelector()) return;
// Show the pattern selector
$rootScope.showSelector = true;
let filtered = false;
// If there is no current pattern, fetch it
if(!appState.getCurrentPattern()) {
const currentPattern = await genericReq.request('GET', '/get-list');
if(!currentPattern.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
appState.setCurrentPattern(currentPattern.data.data[0].id);
} else {
// If there is current pattern, check if there is some pattern
const patternList = await genericReq.request('GET', '/get-list');
if(!patternList.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
// Check if the current pattern cookie is valid
filtered = patternList.data.data.filter(item => item.id.includes(appState.getCurrentPattern()))
if(!filtered.length) appState.setCurrentPattern(patternList.data.data[0].id)
}
const data = filtered ? filtered : await courier.indexPatterns.get(appState.getCurrentPattern());
$scope.theresPattern = true;
$scope.currentPattern = data.title;
const list = await patternHandler.getPatternList();
// Getting the list of index patterns
if(list) {
$scope.patternList = list;
$scope.currentSelectedPattern = appState.getCurrentPattern();
}
if(!$scope.$$phase) $scope.$digest();
if(!$rootScope.$$phase) $rootScope.$digest();
return;
} catch (error) {
errorHandler.handle(error,'Directives - Menu');
$scope.theresPattern = false;
}
}
load();
// Function to change the current index pattern on the app
$scope.changePattern = async selectedPattern => {
try{
if(!appState.getPatternSelector()) return;
$scope.currentSelectedPattern = await patternHandler.changePattern(selectedPattern);
if(!$scope.$$phase) $scope.$digest();
$window.location.reload();
return;
}catch(error){
errorHandler.handle(error,'Directives - Menu');
}
}
$scope.$on('updateAPI', (evt,params) => {
const current = appState.getCurrentAPI();
if(current) {
const parsed = JSON.parse(current);
// If we've received cluster info as parameter, it means we must update our stored cookie
if(params && params.cluster_info){
if(params.cluster_info.status === 'enabled'){
parsed.name = params.cluster_info.cluster;
} else {
parsed.name = params.cluster_info.manager;
}
appState.setCurrentAPI(JSON.stringify(parsed));
}
$scope.theresAPI = true;
$scope.currentAPI = parsed.name;
} else {
$scope.theresAPI = false;
}
$scope.$on('updatePattern', () => {
if(!appState.getPatternSelector()) return;
courier.indexPatterns.get(appState.getCurrentPattern())
.then(data => {
$scope.theresPattern = true;
$scope.currentSelectedPattern = appState.getCurrentPattern();
})
.catch(error => {
errorHandler.handle(error,'Directives - Menu');
$scope.theresPattern = false;
});
});
}
}
$scope.$on('updatePattern', () => {
if(!appState.getPatternSelector()) return;
courier.indexPatterns.get(appState.getCurrentPattern())
.then(data => {
$scope.theresPattern = true;
$scope.currentSelectedPattern = appState.getCurrentPattern();
})
.catch(error => {
errorHandler.handle(error,'Directives - Menu');
$scope.theresPattern = false;
});
});
},
template: menuTemplate
};
});
app.directive('wzMenu', () => new WzMenu());

View File

@ -15,21 +15,24 @@ import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
app.directive('wzWelcomeCard',function(){
return {
restrict: 'E',
scope: {
class WzWelcomeCard {
constructor() {
this.restrict = 'E';
this.scope = {
title: '=title',
description: '=description',
logo: '=logo',
switchTab: '&',
currentTab: '=currentTab',
wzLogo: '=wzLogo'
},
replace: true,
link: function(scope,elm,attrs){
scope.callSwitchTab = () => scope.switchTab();
},
template
};
});
};
this.replace = true;
this.template = template;
}
link(scope, elm, attrs) { // eslint-disable-line
scope.callSwitchTab = () => scope.switchTab();
}
}
app.directive('wzWelcomeCard',() => new WzWelcomeCard());

View File

@ -14,24 +14,22 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('discoverPendingUpdates', function() {
let pendingUpdates = [];
const addItem = (query, filters) => {
pendingUpdates.push(query, filters);
class DiscoverPendingUpdates {
constructor(){
this.pendingUpdates = [];
}
const getList = () => {
return pendingUpdates;
addItem (query, filters) {
this.pendingUpdates.push(query, filters);
}
const removeAll = () => {
pendingUpdates = [];
getList () {
return this.pendingUpdates;
}
return {
addItem : addItem,
getList : getList,
removeAll : removeAll
};
});
removeAll () {
this.pendingUpdates = [];
}
}
app.service('discoverPendingUpdates', DiscoverPendingUpdates);

View File

@ -14,24 +14,22 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('loadedVisualizations', function() {
let list = [];
const addItem = item => {
list.push(item);
class LoadedVisualizations {
constructor(){
this.list = [];
}
const getList = () => {
return list;
addItem(item) {
this.list.push(item);
}
const removeAll = () => {
list = [];
getList() {
return this.list;
}
return {
addItem : addItem,
getList : getList,
removeAll : removeAll
};
});
removeAll() {
this.list = [];
}
}
app.service('loadedVisualizations', LoadedVisualizations);

View File

@ -14,24 +14,47 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('wzMisc', function() {
const state = {
apiIsDown: false,
comeFromWizard: false,
blankScreenError: false
class WzMisc {
constructor() {
this.state = {
apiIsDown : false,
comeFromWizard : false,
blankScreenError: false,
lastRestart : null
}
}
const setApiIsDown = value => state.apiIsDown = value;
const setWizard = value => state.comeFromWizard = value;
const setGeneric = (key,value) => state[key] = value;
const setBlankScr = value => state.blankScreenError = value;
const getValue = key => state[key];
return {
setGeneric,
setApiIsDown,
setWizard,
setBlankScr,
getValue
};
});
setApiIsDown (value) {
this.state.apiIsDown = value;
}
getApiIsDown() {
return this.state.apiIsDown;
}
setWizard (value) {
this.state.comeFromWizard = value;
}
getWizard() {
return this.state.comeFromWizard;
}
setBlankScr (value) {
this.state.blankScreenError = value;
}
getBlankScr() {
return this.state.blankScreenError;
}
setLastRestart (value) {
this.state.lastRestart = value;
}
getLastRestart() {
return this.state.lastRestart;
}
}
app.service('wzMisc', WzMisc);

View File

@ -13,29 +13,26 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('rawVisualizations', function() {
let list = [];
const addItem = item => {
list.push(item);
class RawVisualizations {
constructor() {
this.list = [];
}
const assignItems = items => {
list = Array.isArray(items) ? items : [];
addItem(item) {
this.list.push(item);
}
const getList = () => {
return list;
assignItems(items) {
this.list = Array.isArray(items) ? items : [];
}
const removeAll = () => {
list = [];
getList() {
return this.list;
}
return {
addItem : addItem,
getList : getList,
removeAll : removeAll,
assignItems: assignItems
};
});
removeAll() {
this.list = [];
}
}
app.service('rawVisualizations', RawVisualizations);

View File

@ -1,29 +1,35 @@
/*
* Wazuh app - Factory to share an agent between controllers
*
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
* Wazuh app - Factory to share an agent between controllers
*
* Copyright (C) 2018 Wazuh, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('shareAgent', function() {
let agent = null;
class ShareAgent {
constructor(){
this.agent = null;
}
const getAgent = () => agent;
const setAgent = in_agent => agent = in_agent;
const deleteAgent = () => agent = null;
return {
getAgent,
setAgent,
deleteAgent
};
});
getAgent() {
return this.agent;
}
setAgent (ag) {
this.agent = ag;
}
deleteAgent() {
this.agent = null;
}
}
app.service('shareAgent', ShareAgent);

View File

@ -14,65 +14,67 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.factory('tabVisualizations', function() {
const agents = {
welcome : 0,
general : 7,
fim : 7,
pm : 4,
vuls : 7,
oscap : 13,
ciscat : 11,
audit : 15,
gdpr : 3,
pci : 3,
virustotal : 6,
configuration: 0
class TabVisualizations {
constructor(){
this.agents = {
welcome : 0,
general : 7,
fim : 7,
pm : 4,
vuls : 7,
oscap : 13,
ciscat : 11,
audit : 15,
gdpr : 3,
pci : 3,
virustotal : 6,
configuration: 0
}
this.overview = {
welcome : 0,
general : 11,
fim : 10,
pm : 5,
vuls : 8,
oscap : 11,
ciscat : 11,
audit : 15,
pci : 6,
gdpr : 6,
aws : 10,
virustotal: 7
}
this.tabVisualizations = {}
this.currentTab = '';
}
const overview = {
welcome : 0,
general : 11,
fim : 10,
pm : 5,
vuls : 8,
oscap : 11,
ciscat : 11,
audit : 15,
pci : 6,
gdpr : 6,
aws : 10,
virustotal: 7
setTab (tab) {
this.currentTab = tab;
}
let tabVisualizations = {}
let currentTab = '';
const setTab = tab => currentTab = tab;
const getTab = () => {
return currentTab;
getTab () {
return this.currentTab;
}
const getItem = item => tabVisualizations[item]
getItem (item) {
return this.tabVisualizations[item];
}
const assign = tabs => {
assign (tabs) {
if(typeof tabs === 'object') {
tabVisualizations = tabs;
this.tabVisualizations = tabs;
} else if(typeof tabs === 'string') {
tabVisualizations = tabs === 'overview' ?
overview :
agents;
this.tabVisualizations = tabs === 'overview' ?
this.overview :
this.agents;
}
}
const removeAll = () => tabVisualizations = {};
removeAll () {
this.tabVisualizations = {};
}
}
return {
getItem,
removeAll,
assign,
setTab,
getTab
};
});
app.service('tabVisualizations', TabVisualizations);

View File

@ -14,18 +14,20 @@ import { uiModules } from 'ui/modules'
import dateMath from '@kbn/datemath';
const app = uiModules.get('app/wazuh', []);
app.factory('visHandlers', function() {
let list = [];
class VisHandlers {
constructor() {
this.list = [];
}
const addItem = item => {
list.push(item);
};
addItem(item) {
this.list.push(item);
}
const getList = () => {
return list;
};
getList() {
return this.list;
}
const getAppliedFilters = syscollector => {
getAppliedFilters(syscollector) {
const appliedFilters = {};
if(syscollector){
@ -42,7 +44,7 @@ app.factory('visHandlers', function() {
}
// Check raw response from all rendered tables
const tables = list.filter(item => item._scope &&
const tables = this.list.filter(item => item._scope &&
item._scope.savedObj &&
item._scope.savedObj.vis &&
item._scope.savedObj.vis._state &&
@ -75,12 +77,12 @@ app.factory('visHandlers', function() {
false;
});
if(list && list.length) {
if(this.list && this.list.length) {
// Parse applied filters for the first visualization
const filters = list[0]._scope.savedObj.vis.API.queryFilter.getFilters();
const filters = this.list[0]._scope.savedObj.vis.API.queryFilter.getFilters();
// Parse current time range
const { from, to } = list[0]._scope.savedObj.vis.API.timeFilter.time;
const { from, to } = this.list[0]._scope.savedObj.vis.API.timeFilter.time;
Object.assign(appliedFilters, {
filters,
@ -88,18 +90,18 @@ app.factory('visHandlers', function() {
from: dateMath.parse(from),
to: dateMath.parse(to)
},
searchBar: list[0] && list[0]._scope && list[0]._scope.appState && list[0]._scope.appState.query && list[0]._scope.appState.query.query ?
list[0]._scope.appState.query.query :
searchBar: this.list[0] && this.list[0]._scope && this.list[0]._scope.appState && this.list[0]._scope.appState.query && this.list[0]._scope.appState.query.query ?
this.list[0]._scope.appState.query.query :
false,
tables
});
}
return appliedFilters;
};
}
const hasData = () => {
for(const item of list) {
hasData() {
for(const item of this.list) {
if(item && item._scope && item._scope.savedObj && item._scope.savedObj.searchSource &&
item._scope.savedObj.searchSource.rawResponse &&
item._scope.savedObj.searchSource.rawResponse.hits &&
@ -108,10 +110,10 @@ app.factory('visHandlers', function() {
}
}
return false;
};
}
const removeAll = () => {
for(const item of list){
removeAll() {
for(const item of this.list){
if(item && item._scope){
item._scope.$destroy();
}
@ -119,14 +121,8 @@ app.factory('visHandlers', function() {
item._scope.savedObj.destroy();
}
}
list = [];
};
return {
addItem,
getList,
removeAll,
hasData,
getAppliedFilters
};
});
this.list = [];
}
}
app.service('visHandlers', VisHandlers);

View File

@ -10,53 +10,55 @@
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import domtoimage from 'dom-to-image'
import domtoimage from 'dom-to-image'
const app = uiModules.get('app/wazuh', []);
app.factory('vis2png', function ($rootScope) {
class Vis2PNG {
constructor($rootScope) {
this.$rootScope = $rootScope;
this.rawArray = [];
this.htmlObject = {};
this.working = false;
}
let rawArray = [];
let htmlObject = {};
let working = false;
const checkArray = async visArray => {
async checkArray (visArray) {
try {
working = true;
this.working = true;
const len = visArray.length;
let currentCompleted = 0;
await Promise.all(visArray.map(async currentValue => {
const tmpNode = htmlObject[currentValue]
const tmpNode = this.htmlObject[currentValue]
try {
const tmpResult = await domtoimage.toPng(tmpNode[0]);
rawArray.push({element:tmpResult,width:tmpNode.width(),height:tmpNode.height(), id: currentValue});
this.rawArray.push({element:tmpResult,width:tmpNode.width(),height:tmpNode.height(), id: currentValue});
} catch (error) {} // eslint-disable-line
currentCompleted++;
$rootScope.reportStatus = `Generating report...${Math.round((currentCompleted/len) * 100)}%`
if(!$rootScope.$$phase) $rootScope.$digest()
this.$rootScope.reportStatus = `Generating report...${Math.round((currentCompleted/len) * 100)}%`
if(!this.$rootScope.$$phase) this.$rootScope.$digest()
}))
working = false;
$rootScope.reportStatus = `Generating PDF document...`
return rawArray;
this.working = false;
this.$rootScope.reportStatus = `Generating PDF document...`
return this.rawArray;
} catch (error) {
working = false;
this.working = false;
return Promise.reject(error);
}
}
const isWorking = () => working;
const clear = () => {
rawArray = [];
htmlObject = {};
isWorking () {
return this.working;
}
const assignHTMLItem = (id,content) => htmlObject[id] = content;
return {
checkArray,
assignHTMLItem,
isWorking,
clear
clear () {
this.rawArray = [];
this.htmlObject = {};
}
});
assignHTMLItem (id,content) {
this.htmlObject[id] = content;
}
}
app.service('vis2png', Vis2PNG);

View File

@ -11,16 +11,20 @@
*/
import { uiModules } from 'ui/modules';
uiModules
.get('app/wazuh', [])
.factory('wazuhConfig',
function() {
const config = {};
const app = uiModules.get('app/wazuh', []);
const setConfig = cfg => Object.assign(config,cfg);
class WazuhConfig {
constructor(){
this.config = {};
}
const getConfig = () => config;
setConfig(cfg) {
Object.assign(this.config, cfg);
}
return { setConfig, getConfig };
getConfig() {
return this.config;
}
}
});
app.service('wazuhConfig',WazuhConfig);

View File

@ -13,35 +13,41 @@ import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
app.service('apiReq', function ($q, genericReq, appState) {
return {
request: async (method, path, body) => {
try {
class ApiRequest {
constructor($q, genericReq, appState) {
this.$q = $q;
this.genericReq = genericReq;
this.appState = appState;
}
if (!method || !path || !body) {
throw new Error('Missing parameters');
}
if (!appState.getCurrentAPI()){
throw new Error('No API selected.');
}
const { id } = JSON.parse(appState.getCurrentAPI());
const requestData = { method, path, body, id };
async request(method, path, body) {
try {
const data = await genericReq.request('POST', '/api/wazuh-api/request', requestData);
if (data.error) {
throw new Error(data.error);
}
return $q.resolve(data);
} catch (error) {
return error && error.data && error.data.message ?
$q.reject(error.data.message) :
$q.reject(error.message || error);
if (!method || !path || !body) {
throw new Error('Missing parameters');
}
if (!this.appState.getCurrentAPI()){
throw new Error('No API selected.');
}
const { id } = JSON.parse(this.appState.getCurrentAPI());
const requestData = { method, path, body, id };
const data = await this.genericReq.request('POST', '/api/wazuh-api/request', requestData);
if (data.error) {
throw new Error(data.error);
}
return this.$q.resolve(data);
} catch (error) {
return error && error.data && error.data.message ?
this.$q.reject(error.data.message) :
this.$q.reject(error.message || error);
}
};
});
}
}
app.service('apiReq', ApiRequest);

View File

@ -14,67 +14,75 @@ import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
app.service('testAPI', function ($http, $rootScope, appState, wzMisc, wazuhConfig) {
return {
check_stored: async data => {
try {
const configuration = wazuhConfig.getConfig();
const timeout = configuration ? configuration.timeout : 8000;
const headers = {headers:{ "Content-Type": 'application/json' }, timeout: timeout || 8000};
class ApiTester {
constructor($http, appState, wzMisc, wazuhConfig) {
this.$http = $http
this.appState = appState;
this.wzMisc = wzMisc;
this.wazuhConfig = wazuhConfig;
}
/** Checks for outdated cookies */
const current = appState.getCreatedAt();
const lastRestart = $rootScope.lastRestart;
if(current && lastRestart && lastRestart > current){
appState.removeCurrentPattern();
appState.removeCurrentAPI();
appState.removeClusterInfo();
appState.removeCreatedAt();
delete $rootScope.lastRestart;
async checkStored(data) {
try {
const configuration = this.wazuhConfig.getConfig();
const timeout = configuration ? configuration.timeout : 8000;
const headers = {headers:{ "Content-Type": 'application/json' }, timeout: timeout || 8000};
appState.setPatternSelector(configuration['ip.selector']);
/** Checks for outdated cookies */
const current = this.appState.getCreatedAt();
const lastRestart = this.wzMisc.getLastRestart();
if(current && lastRestart && lastRestart > current){
this.appState.removeCurrentPattern();
this.appState.removeCurrentAPI();
this.appState.removeClusterInfo();
this.appState.removeCreatedAt();
this.wzMisc.setLastRestart(null);
return 'cookies_outdated';
/** End of checks for outdated cookies */
this.appState.setPatternSelector(configuration['ip.selector']);
} else {
return 'cookies_outdated';
/** End of checks for outdated cookies */
const result = await $http.post(chrome.addBasePath('/api/wazuh-api/checkStoredAPI'), data,headers);
} else {
appState.setPatternSelector(configuration['ip.selector']);
const result = await this.$http.post(chrome.addBasePath('/api/wazuh-api/checkStoredAPI'), data,headers);
if(result.error) {
return Promise.reject(result);
}
return result;
this.appState.setPatternSelector(configuration['ip.selector']);
if(result.error) {
return Promise.reject(result);
}
} catch (error) {
if(error.status && error.status === -1){
wzMisc.setApiIsDown(true);
}
return Promise.reject(error);
}
},
check: async data => {
try {
const { timeout } = wazuhConfig.getConfig();
const headers = {headers:{ "Content-Type": 'application/json' },timeout: timeout || 8000};
const url = chrome.addBasePath("/api/wazuh-api/checkAPI");
const response = await $http.post(url, data, headers);
if (response.error) {
return Promise.reject(response);
}
return response;
} catch(error) {
return Promise.reject(error);
return result;
}
} catch (error) {
if(error.status && error.status === -1){
this.wzMisc.setApiIsDown(true);
}
return Promise.reject(error);
}
};
});
}
async check(data) {
try {
const { timeout } = this.wazuhConfig.getConfig();
const headers = {headers:{ "Content-Type": 'application/json' },timeout: timeout || 8000};
const url = chrome.addBasePath("/api/wazuh-api/checkAPI");
const response = await this.$http.post(url, data, headers);
if (response.error) {
return Promise.reject(response);
}
return response;
} catch(error) {
return Promise.reject(error);
}
}
}
app.service('testAPI', ApiTester);

View File

@ -11,83 +11,106 @@
*/
import { uiModules } from 'ui/modules'
uiModules.get('app/wazuh', [])
.service('appState', function ($cookies, $window) {
return {
getExtensions: id => {
const current = $cookies.getObject('extensions');
return current ? current[id] : false;
},
setExtensions: (id,extensions) => {
const current = $cookies.getObject('extensions') || {};
current[id] = extensions;
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (extensions) {
$cookies.putObject('extensions', current, { 'expires': exp });
}
},
getClusterInfo: () => {
return $cookies.getObject('_clusterInfo');
},
removeClusterInfo: () => {
return $cookies.remove('_clusterInfo');
},
setClusterInfo: cluster_info => {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (cluster_info) {
$cookies.putObject('_clusterInfo', cluster_info, { 'expires': exp });
}
},
getCurrentPattern: () => {
return $cookies.getObject('_currentPattern');
},
setCreatedAt: date => {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
$cookies.putObject('_createdAt',date,{ 'expires': exp });
},
setCurrentPattern: newPattern => {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (newPattern) {
$cookies.putObject('_currentPattern', newPattern, { 'expires': exp });
}
},
removeCurrentPattern: () => {
return $cookies.remove('_currentPattern');
},
getCreatedAt: () => {
return $cookies.getObject('_createdAt');
},
removeCreatedAt: () => {
return $cookies.remove('_createdAt');
},
getCurrentAPI: () => {
return $cookies.getObject('API');
},
removeCurrentAPI: () => {
return $cookies.remove('API');
},
setCurrentAPI: API => {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (API) {
$cookies.putObject('API', API, { 'expires': exp});
}
},
getPatternSelector: () => {
return $cookies.getObject('patternSelector');
},
setPatternSelector: value => {
$cookies.putObject('patternSelector', value);
},
setCurrentDevTools: current => {
$window.localStorage.setItem('currentDevTools',current);
},
getCurrentDevTools: () => {
return $window.localStorage.getItem('currentDevTools')
const app = uiModules.get('app/wazuh', [])
class AppState {
constructor($cookies, $window) {
this.$cookies = $cookies;
this.$window = $window;
}
getExtensions(id) {
const current = this.$cookies.getObject('extensions');
return current ? current[id] : false;
}
setExtensions(id,extensions) {
const current = this.$cookies.getObject('extensions') || {};
current[id] = extensions;
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (extensions) {
this.$cookies.putObject('extensions', current, { 'expires': exp });
}
};
});
}
getClusterInfo() {
return this.$cookies.getObject('_clusterInfo');
}
removeClusterInfo() {
return this.$cookies.remove('_clusterInfo');
}
setClusterInfo(cluster_info) {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (cluster_info) {
this.$cookies.putObject('_clusterInfo', cluster_info, { 'expires': exp });
}
}
getCurrentPattern() {
return this.$cookies.getObject('_currentPattern');
}
setCreatedAt(date) {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
this.$cookies.putObject('_createdAt',date,{ 'expires': exp });
}
setCurrentPattern(newPattern) {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (newPattern) {
this.$cookies.putObject('_currentPattern', newPattern, { 'expires': exp });
}
}
removeCurrentPattern() {
return this.$cookies.remove('_currentPattern');
}
getCreatedAt() {
return this.$cookies.getObject('_createdAt');
}
removeCreatedAt() {
return this.$cookies.remove('_createdAt');
}
getCurrentAPI() {
return this.$cookies.getObject('API');
}
removeCurrentAPI() {
return this.$cookies.remove('API');
}
setCurrentAPI(API) {
const exp = new Date();
exp.setDate(exp.getDate() + 365);
if (API) {
this.$cookies.putObject('API', API, { 'expires': exp});
}
}
getPatternSelector() {
return this.$cookies.getObject('patternSelector');
}
setPatternSelector(value) {
this.$cookies.putObject('patternSelector', value);
}
setCurrentDevTools(current) {
this.$window.localStorage.setItem('currentDevTools',current);
}
getCurrentDevTools() {
return this.$window.localStorage.getItem('currentDevTools')
}
}
app.service('appState', AppState);

View File

@ -13,9 +13,18 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.service('commonData', function ($rootScope, $timeout, genericReq, appState, errorHandler, $location, shareAgent) {
class CommonData {
constructor($rootScope, $timeout, genericReq, appState, errorHandler, $location, shareAgent) {
this.$rootScope = $rootScope;
this.$timeout = $timeout;
this.genericReq = genericReq;
this.appState = appState;
this.errorHandler = errorHandler;
this.$location = $location;
this.shareAgent = shareAgent;
}
const af = (filterHandler, tab, localChange, agent) => {
af(filterHandler, tab, localChange, agent) {
try{
const tabFilters = {
general : { group: '' },
@ -32,11 +41,11 @@ app.service('commonData', function ($rootScope, $timeout, genericReq, appState,
};
const filters = [];
const isCluster = appState.getClusterInfo().status == 'enabled';
const isCluster = this.appState.getClusterInfo().status == 'enabled';
filters.push(filterHandler.managerQuery(
isCluster ?
appState.getClusterInfo().cluster :
appState.getClusterInfo().manager,
this.appState.getClusterInfo().cluster :
this.appState.getClusterInfo().manager,
isCluster
))
@ -50,91 +59,99 @@ app.service('commonData', function ($rootScope, $timeout, genericReq, appState,
}
}
if(agent) filters.push(filterHandler.agentQuery(agent));
$rootScope.$emit('wzEventFilters',{filters, localChange});
if(!$rootScope.$$listenerCount['wzEventFilters']){
$timeout(100)
.then(() => af(filterHandler, tab, localChange, agent = false))
this.$rootScope.$emit('wzEventFilters',{filters, localChange});
if(!this.$rootScope.$$listenerCount['wzEventFilters']){
this.$timeout(100)
.then(() => this.af(filterHandler, tab, localChange, agent = false))
}
} catch(error) {
errorHandler.handle('An error occurred while creating custom filters for visualizations',agent ? 'Agents' : 'Overview',true);
this.errorHandler.handle('An error occurred while creating custom filters for visualizations', agent ? 'Agents' : 'Overview',true);
}
};
return {
getGDPR: async () => {
try {
const gdprTabs = [];
const data = await genericReq.request('GET', '/api/wazuh-api/gdpr/all')
if(!data.data) return [];
for(const key in data.data){
gdprTabs.push({ title: key, content: data.data[key] });
}
return gdprTabs;
} catch(error) {
return Promise.reject(error);
}
},
getPCI: async () => {
try {
const pciTabs = [];
const data = await genericReq.request('GET', '/api/wazuh-api/pci/all')
if(!data.data) return [];
for(const key in data.data){
pciTabs.push({ title: key, content: data.data[key] });
}
return pciTabs;
} catch(error) {
return Promise.reject(error);
}
},
assignFilters: (filterHandler, tab, localChange, agent) => af(filterHandler, tab, localChange, agent),
validateRange: data => {
const result = {
duration : 'Unknown',
inProgress: false,
end : data.end || 'Unknown',
start : data.start || 'Unknown'
}
}
if(data.end && data.start) {
result.duration = ((new Date(data.end) - new Date(data.start))/1000)/60;
result.duration = Math.round(result.duration * 100) / 100;
if(result.duration <= 0){
result.inProgress = true;
}
async getGDPR() {
try {
const gdprTabs = [];
const data = await this.genericReq.request('GET', '/api/wazuh-api/gdpr/all')
if(!data.data) return [];
for(const key in data.data){
gdprTabs.push({ title: key, content: data.data[key] });
}
return gdprTabs;
} catch(error) {
return Promise.reject(error);
}
}
return result;
},
checkTabLocation: () => {
if ($location.search().tab){
return $location.search().tab;
} else {
$location.search('tab', 'welcome');
return 'welcome';
}
},
checkTabViewLocation: () => {
if ($location.search().tabView){
return $location.search().tabView;
} else {
$location.search('tabView', 'panels');
return 'panels'
async getPCI() {
try {
const pciTabs = [];
const data = await this.genericReq.request('GET', '/api/wazuh-api/pci/all')
if(!data.data) return [];
for(const key in data.data){
pciTabs.push({ title: key, content: data.data[key] });
}
return pciTabs;
} catch(error) {
return Promise.reject(error);
}
}
},
checkLocationAgentId: (newAgentId, globalAgent) => {
if (newAgentId) {
$location.search('agent', newAgentId);
return newAgentId;
assignFilters(filterHandler, tab, localChange, agent) {
return this.af(filterHandler, tab, localChange, agent);
}
validateRange(data) {
const result = {
duration : 'Unknown',
inProgress: false,
end : data.end || 'Unknown',
start : data.start || 'Unknown'
}
if(data.end && data.start) {
result.duration = ((new Date(data.end) - new Date(data.start))/1000)/60;
result.duration = Math.round(result.duration * 100) / 100;
if(result.duration <= 0){
result.inProgress = true;
}
}
return result;
}
checkTabLocation() {
if (this.$location.search().tab){
return this.$location.search().tab;
} else {
this.$location.search('tab', 'welcome');
return 'welcome';
}
}
checkTabViewLocation() {
if (this.$location.search().tabView){
return this.$location.search().tabView;
} else {
this.$location.search('tabView', 'panels');
return 'panels'
}
}
checkLocationAgentId(newAgentId, globalAgent) {
if (newAgentId) {
this.$location.search('agent', newAgentId);
return newAgentId;
} else {
if (this.$location.search().agent && !globalAgent) { // There's one in the url
return this.$location.search().agent;
} else {
if ($location.search().agent && !globalAgent) { // There's one in the url
return $location.search().agent;
} else {
shareAgent.deleteAgent();
$location.search('agent', globalAgent.id);
return globalAgent.id;
}
this.shareAgent.deleteAgent();
this.$location.search('agent', globalAgent.id);
return globalAgent.id;
}
}
}
});
}
app.service('commonData', CommonData);

View File

@ -13,15 +13,29 @@ import { uiModules } from 'ui/modules'
const app = uiModules.get('app/wazuh', []);
app.service('csvReq', function (genericReq) {
return {
fetch: async (path, id, filters = null) => {
try {
const output = await genericReq.request('POST','/api/wazuh-api/csv',{ path, id, filters });
return output.data;
} catch (error) {
return Promise.reject(error);
}
class CSVRequest {
/**
* Constructor
* @param {*} genericReq Service to make requests to our server
*/
constructor(genericReq) {
this.genericReq = genericReq;
}
/**
* It fetchs data from /api/wazuh-api/csv route using the below parameters.
* @param {string} path Wazuh API route
* @param {number|string} id Elasticsearch document ID
* @param {*} filters Array of Wazuh API filters. Optional
*/
async fetch(path, id, filters = null) {
try {
const output = await this.genericReq.request('POST','/api/wazuh-api/csv',{ path, id, filters });
return output.data;
} catch (error) {
return Promise.reject(error);
}
}
});
}
app.service('csvReq', CSVRequest);

View File

@ -13,10 +13,22 @@ import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
app.service('errorHandler', function ( Notifier, $location) {
const notify = new Notifier();
class ErrorHandler {
/**
* Constructor
* @param {*} Notifier Useful class to create toasts
* @param {*} $location Angular.js service to manage URL routing
*/
constructor(Notifier, $location) {
this.$location = $location;
this.notify = new Notifier();
}
const extractMessage = error => {
/**
* Extracts error message string from any kind of error.
* @param {*} error
*/
extractMessage(error) {
if(error && error.status && error.status === -1) return 'Server did not respond';
if(error.data && error.data.errorData && error.data.errorData.message) return error.data.errorData.message;
if(error.errorData && error.errorData.message) return error.errorData.message;
@ -32,37 +44,53 @@ app.service('errorHandler', function ( Notifier, $location) {
return error || 'Unexpected error';
}
const isAPIUnauthorized = error => (error && error.data && parseInt(error.data.statusCode) === 500 && parseInt(error.data.error) === 7 && error.data.message === '401 Unauthorized');
/**
* Returns true/false depending on the error content. It looks for unauthorized error.
* @param {*} error
*/
isAPIUnauthorized(error){
return (error && error.data && parseInt(error.data.statusCode) === 500 && parseInt(error.data.error) === 7 && error.data.message === '401 Unauthorized');
}
const info = (message,location) => {
/**
* Fires a green toast (success toast) using given message
* @param {string} message The message to be shown
* @param {string} location Usually means the file where this method was called
*/
info(message,location) {
if(typeof message === 'string') {
message = location ? location + '. ' + message : message;
notify.custom(message,{ title: 'Information', icon: 'info', type: 'info'});
this.notify.custom(message,{ title: 'Information', icon: 'info', type: 'info'});
}
return;
}
const handle = (error,location,isWarning,silent) => {
if(isAPIUnauthorized(error)){
$location.path('/settings');
/**
* Main method to show error, warning or info messages
* @param {*} error
* @param {string} location Usually means the file where this method was called
* @param {boolean} isWarning If true, the toast is yellow
* @param {boolean} silent If true, no message is shown
*/
handle(error,location,isWarning,silent) {
if(this.isAPIUnauthorized(error)){
this.$location.path('/settings');
return;
}
const message = extractMessage(error);
const message = this.extractMessage(error);
let text;
text = isWarning ? `Warning. ${message}` : `Error. ${message}`;
if(error.extraMessage) text = error.extraMessage;
text = location ? location + '. ' + text : text;
if(!silent){
if(isWarning || (text && typeof text === 'string' && text.toLowerCase().includes('no results'))) notify.warning(text);
else notify.error(text);
if(isWarning || (text && typeof text === 'string' && text.toLowerCase().includes('no results'))) this.notify.warning(text);
else this.notify.error(text);
}
return text;
}
return {
handle: handle,
info: info
}
});
}
app.service('errorHandler', ErrorHandler);

View File

@ -14,45 +14,58 @@ import { uiModules } from 'ui/modules';
const app = uiModules.get('app/wazuh', []);
app.service('genericReq', function ($q, $http, appState, wazuhConfig) {
return {
request: async (method, path, payload = null) => {
try {
if (!method || !path) {
throw new Error('Missing parameters');
}
class GenericRequest {
constructor($q, $http, appState, wazuhConfig) {
this.$q = $q;
this.$http = $http;
this.appState = appState;
this.wazuhConfig = wazuhConfig;
}
const { timeout } = wazuhConfig.getConfig();
const requestHeaders = { headers: { "Content-Type": 'application/json' }, timeout: timeout || 8000 };
const tmpUrl = chrome.addBasePath(path);
requestHeaders.headers.pattern = appState.getCurrentPattern();
try {
requestHeaders.headers.id = JSON.parse(appState.getCurrentAPI()).id;
} catch (error) {
// Intended
}
const data = {};
if (method === "GET") Object.assign(data, await $http.get(tmpUrl, requestHeaders));
if (method === "PUT") Object.assign(data, await $http.put(tmpUrl, payload, requestHeaders));
if (method === "POST") Object.assign(data, await $http.post(tmpUrl, payload, requestHeaders));
if (method === "DELETE") Object.assign(data, await $http.delete(tmpUrl));
if (!data) {
throw new Error(`Error doing a request to ${tmpUrl}, method: ${method}.`);
}
if (data.error && data.error !== '0') {
throw new Error(data.error);
}
return $q.resolve(data);
} catch (error) {
return $q.reject(error);
/**
* Executes a request to a remote host
* @param {string} method Request method (GET, PUT, POST, DELETE)
* @param {string} path Relative path to the remote host
* @param {object} payload
*/
async request(method, path, payload = null) {
try {
if (!method || !path) {
throw new Error('Missing parameters');
}
const { timeout } = this.wazuhConfig.getConfig();
const requestHeaders = { headers: { "Content-Type": 'application/json' }, timeout: timeout || 8000 };
const tmpUrl = chrome.addBasePath(path);
requestHeaders.headers.pattern = this.appState.getCurrentPattern();
try {
requestHeaders.headers.id = JSON.parse(this.appState.getCurrentAPI()).id;
} catch (error) {
// Intended
}
const data = {};
if (method === "GET") Object.assign(data, await this.$http.get(tmpUrl, requestHeaders));
if (method === "PUT") Object.assign(data, await this.$http.put(tmpUrl, payload, requestHeaders));
if (method === "POST") Object.assign(data, await this.$http.post(tmpUrl, payload, requestHeaders));
if (method === "DELETE") Object.assign(data, await this.$http.delete(tmpUrl));
if (!data) {
throw new Error(`Error doing a request to ${tmpUrl}, method: ${method}.`);
}
if (data.error && data.error !== '0') {
throw new Error(data.error);
}
return this.$q.resolve(data);
} catch (error) {
return this.$q.reject(error);
}
};
});
}
}
app.service('genericReq', GenericRequest);

View File

@ -11,40 +11,50 @@
*/
import { uiModules } from 'ui/modules'
uiModules.get('app/wazuh', [])
.service('patternHandler', function ($location, genericReq, appState, errorHandler, wzMisc) {
return {
getPatternList: async () => {
try {
const patternList = await genericReq.request('GET','/get-list',{});
const app = uiModules.get('app/wazuh', []);
if(!patternList.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
class PatternHandler {
constructor($location, genericReq, appState, errorHandler, wzMisc) {
this.$location = $location;
this.genericReq = genericReq;
this.appState = appState;
this.errorHandler = errorHandler;
this.wzMisc = wzMisc;
}
if(appState.getCurrentPattern()){
let filtered = patternList.data.data.filter(item => item.id.includes(appState.getCurrentPattern()))
if(!filtered.length) appState.setCurrentPattern(patternList.data.data[0].id)
}
async getPatternList() {
try {
const patternList = await this.genericReq.request('GET','/get-list',{});
return patternList.data.data;
} catch (error) {
errorHandler.handle(error,'Pattern Handler (getPatternList)');
if(!patternList.data.data.length){
this.wzMisc.setBlankScr('Sorry but no valid index patterns were found')
this.$location.search('tab',null);
this.$location.path('/blank-screen');
return;
}
return;
},
changePattern: async selectedPattern => {
try {
appState.setCurrentPattern(selectedPattern);
await genericReq.request('GET',`/refresh-fields/${selectedPattern}`,{})
return appState.getCurrentPattern();
} catch (error) {
errorHandler.handle(error,'Pattern Handler (changePattern)');
if(this.appState.getCurrentPattern()){
let filtered = patternList.data.data.filter(item => item.id.includes(this.appState.getCurrentPattern()))
if(!filtered.length) this.appState.setCurrentPattern(patternList.data.data[0].id)
}
return;
return patternList.data.data;
} catch (error) {
this.errorHandler.handle(error,'Pattern Handler (getPatternList)');
}
};
});
return;
}
async changePattern(selectedPattern) {
try {
this.appState.setCurrentPattern(selectedPattern);
await this.genericReq.request('GET',`/refresh-fields/${selectedPattern}`,{})
return this.appState.getCurrentPattern();
} catch (error) {
this.errorHandler.handle(error,'Pattern Handler (changePattern)');
}
return;
}
}
app.service('patternHandler', PatternHandler);

View File

@ -12,59 +12,69 @@
import { uiModules } from 'ui/modules';
import $ from 'jquery';
uiModules.get('app/wazuh', [])
.service('reportingService', function ($rootScope, vis2png, rawVisualizations, visHandlers, genericReq, errorHandler) {
return {
startVis2Png: async (tab, isAgents = false, syscollectorFilters = null) => {
try {
if(vis2png.isWorking()){
errorHandler.handle('Report in progress', 'Reporting',true);
return;
}
$rootScope.reportBusy = true;
$rootScope.reportStatus = 'Generating report...0%';
if(!$rootScope.$$phase) $rootScope.$digest();
const app = uiModules.get('app/wazuh', []);
vis2png.clear();
const idArray = rawVisualizations.getList().map(item => item.id);
for(const item of idArray) {
const tmpHTMLElement = $(`#${item}`);
vis2png.assignHTMLItem(item,tmpHTMLElement);
}
const appliedFilters = visHandlers.getAppliedFilters(syscollectorFilters);
const array = await vis2png.checkArray(idArray);
const name = `wazuh-${isAgents ? 'agents' : 'overview'}-${tab}-${Date.now() / 1000 | 0}.pdf`
const data = {
array,
name,
title: isAgents ? `Agents ${tab}` : `Overview ${tab}`,
filters: appliedFilters.filters,
time: appliedFilters.time,
searchBar: appliedFilters.searchBar,
tables: appliedFilters.tables,
tab,
section: isAgents ? 'agents' : 'overview',
isAgents
};
await genericReq.request('POST','/api/wazuh-reporting/report',data);
$rootScope.reportBusy = false;
$rootScope.reportStatus = false;
errorHandler.info('Success. Go to Management -> Reporting', 'Reporting')
class ReportingService {
constructor($rootScope, vis2png, rawVisualizations, visHandlers, genericReq, errorHandler) {
this.$rootScope = $rootScope;
this.vis2png = vis2png;
this.rawVisualizations = rawVisualizations;
this.visHandlers = visHandlers;
this.genericReq = genericReq;
this.errorHandler = errorHandler;
}
async startVis2Png(tab, isAgents = false, syscollectorFilters = null) {
try {
if(this.vis2png.isWorking()){
this.errorHandler.handle('Report in progress', 'Reporting',true);
return;
} catch (error) {
$rootScope.reportBusy = false;
$rootScope.reportStatus = false;
errorHandler.handle(error, 'Reporting');
}
this.$rootScope.reportBusy = true;
this.$rootScope.reportStatus = 'Generating report...0%';
if(!this.$rootScope.$$phase) this.$rootScope.$digest();
this.vis2png.clear();
const idArray = this.rawVisualizations.getList().map(item => item.id);
for(const item of idArray) {
const tmpHTMLElement = $(`#${item}`);
this.vis2png.assignHTMLItem(item,tmpHTMLElement);
}
const appliedFilters = this.visHandlers.getAppliedFilters(syscollectorFilters);
const array = await this.vis2png.checkArray(idArray);
const name = `wazuh-${isAgents ? 'agents' : 'overview'}-${tab}-${Date.now() / 1000 | 0}.pdf`
const data = {
array,
name,
title: isAgents ? `Agents ${tab}` : `Overview ${tab}`,
filters: appliedFilters.filters,
time: appliedFilters.time,
searchBar: appliedFilters.searchBar,
tables: appliedFilters.tables,
tab,
section: isAgents ? 'agents' : 'overview',
isAgents
};
await this.genericReq.request('POST','/api/wazuh-reporting/report',data);
this.$rootScope.reportBusy = false;
this.$rootScope.reportStatus = false;
this.errorHandler.info('Success. Go to Management -> Reporting', 'Reporting')
return;
} catch (error) {
this.$rootScope.reportBusy = false;
this.$rootScope.reportStatus = false;
this.errorHandler.handle(error, 'Reporting');
}
};
});
}
}
app.service('reportingService', ReportingService);

View File

@ -9,14 +9,13 @@
*
* Find more information about this on the LICENSE file.
*/
export default async (appState, genericReq, $rootScope, $location, wzMisc) => {
export default async (appState, genericReq, $location, wzMisc) => {
try {
const data = await genericReq.request('GET', '/api/wazuh-elastic/timestamp');
const current = appState.getCreatedAt();
if(data && data.data){
if(!current) appState.setCreatedAt(data.data.lastRestart);
$rootScope.lastRestart = data.data.lastRestart;
if(!$rootScope.$$phase) $rootScope.$digest();
wzMisc.setLastRestart(data.data.lastRestart);
} else {
wzMisc.setBlankScr('Your .wazuh-version index is empty or corrupt.')
$location.search('tab',null);

View File

@ -17,63 +17,63 @@ import healthCheck from './health-check'
export default (courier, $q, $rootScope, $window, $location, Private, appState, genericReq,errorHandler, wzMisc) => {
const deferred = $q.defer();
const catchFunction = error => {
deferred.reject(error);
wzMisc.setBlankScr(errorHandler.handle(error,'Elasticsearch',false,true));
$location.path('/blank-screen');
const buildSavedObjectsClient = async () => {
try {
const savedObjectsClient = Private(SavedObjectsClientProvider);
const savedObjectsData = await savedObjectsClient.find({
type : 'index-pattern',
fields : ['title'],
perPage: 10000
});
const { savedObjects } = savedObjectsData;
const data = await genericReq.request('GET', '/get-list')
let currentPattern = '';
if (appState.getCurrentPattern()) { // There's cookie for the pattern
currentPattern = appState.getCurrentPattern();
} else {
if(!data || !data.data || !data.data.data || !data.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
currentPattern = data.data.data[0].id;
appState.setCurrentPattern(currentPattern);
}
const onlyWazuhAlerts = savedObjects.filter(element => element.id === currentPattern);
if (!onlyWazuhAlerts || !onlyWazuhAlerts.length) { // There's now selected ip
deferred.resolve('No ip');
return;
}
const courierData = await courier.indexPatterns.get(currentPattern)
deferred.resolve({
list : onlyWazuhAlerts,
loaded : courierData,
stateVal : null,
stateValFound: false
});
} catch (error) {
deferred.reject(error);
wzMisc.setBlankScr(errorHandler.handle(error,'Elasticsearch',false,true));
$location.path('/blank-screen');
}
}
if (healthCheck($window, $rootScope)) {
deferred.reject();
$location.path('/health-check');
} else {
const savedObjectsClient = Private(SavedObjectsClientProvider);
savedObjectsClient.find({
type : 'index-pattern',
fields : ['title'],
perPage: 10000
})
.then(({ savedObjects }) => {
genericReq.request('GET', '/get-list')
.then(data => {
let currentPattern = '';
if (appState.getCurrentPattern()) { // There's cookie for the pattern
currentPattern = appState.getCurrentPattern();
} else {
if(!data || !data.data || !data.data.data || !data.data.data.length){
wzMisc.setBlankScr('Sorry but no valid index patterns were found')
$location.search('tab',null);
$location.path('/blank-screen');
return;
}
currentPattern = data.data.data[0].id;
appState.setCurrentPattern(currentPattern);
}
const onlyWazuhAlerts = savedObjects.filter(element => element.id === currentPattern);
if (!onlyWazuhAlerts || !onlyWazuhAlerts.length) { // There's now selected ip
deferred.resolve('No ip');
return;
}
courier.indexPatterns.get(currentPattern)
.then(data => {
deferred.resolve({
list : onlyWazuhAlerts,
loaded : data,
stateVal : null,
stateValFound: false
});
})
.catch(catchFunction);
})
.catch(catchFunction);
})
.catch(catchFunction);
buildSavedObjectsClient();
}
return deferred.promise;
}

View File

@ -94,8 +94,8 @@ export default ($rootScope, $location, $q, $window, testAPI, appState, genericRe
appState.setExtensions(currentApi,extensions);
}
checkTimestamp(appState, genericReq, $rootScope, $location, wzMisc)
.then(() => testAPI.check_stored(currentApi))
checkTimestamp(appState, genericReq, $location, wzMisc)
.then(() => testAPI.checkStored(currentApi))
.then(data => {
if(data && data === 'cookies_outdated'){
$location.search('tab','welcome');
@ -139,7 +139,7 @@ export default ($rootScope, $location, $q, $window, testAPI, appState, genericRe
appState.setCurrentAPI(JSON.stringify({name: apiEntries[0]._source.cluster_info.manager, id: apiEntries[0]._id }));
callCheckStored();
} else {
const comeFromWizard = wzMisc.getValue('comeFromWizard');
const comeFromWizard = wzMisc.getWizard();
!comeFromWizard && errorHandler.handle('Wazuh App: Please set up Wazuh API credentials.','Routes',true);
wzMisc.setWizard(true);
if(!$location.path().includes("/settings")) {

View File

@ -20,7 +20,7 @@ import { settingsWizard, getSavedSearch, goToKibana, getIp, getWzConfig } from '
import healthCheckTemplate from '../templates/health-check/health-check.html'
import agentsTemplate from '../templates/agents/agents.jade'
import agentsPrevTemplate from '../templates/agents-prev/agents-prev.jade'
import managerTemplate from '../templates/manager/manager.jade'
import managementTemplate from '../templates/management/management.jade'
import overviewTemplate from '../templates/overview/overview.jade'
import discoverTemplate from '../templates/discover/discover.jade'
import settingsTemplate from '../templates/settings/settings.jade'
@ -80,7 +80,7 @@ routes
resolve: { nestedResolve }
})
.when('/manager/:tab?/', {
template: managerTemplate,
template: managementTemplate,
resolve: { nestedResolve, ip, savedSearch }
})
.when('/overview/', {

View File

@ -10,54 +10,59 @@
* Find more information about this on the LICENSE file.
*/
import { uiModules } from 'ui/modules'
import $ from 'jquery'
uiModules.get('app/wazuh', [])
.service('visFactoryService', function ($rootScope, appState, genericReq, discoverPendingUpdates, rawVisualizations, tabVisualizations, loadedVisualizations, commonData, visHandlers) {
const clear = (onlyAgent = false) => {
if(!onlyAgent) visHandlers.removeAll();
discoverPendingUpdates.removeAll();
rawVisualizations.removeAll();
loadedVisualizations.removeAll();
const app = uiModules.get('app/wazuh', []);
class VisFactoryService {
constructor($rootScope, appState, genericReq, discoverPendingUpdates, rawVisualizations, tabVisualizations, loadedVisualizations, commonData, visHandlers) {
this.$rootScope = $rootScope;
this.appState = appState;
this.genericReq = genericReq;
this.discoverPendingUpdates = discoverPendingUpdates;
this.rawVisualizations = rawVisualizations;
this.tabVisualizations = tabVisualizations;
this.loadedVisualizations = loadedVisualizations;
this.commonData = commonData;
this.visHandlers = visHandlers;
}
const clearAll = () => {
clear();
tabVisualizations.removeAll();
clear(onlyAgent = false) {
if(!onlyAgent) this.visHandlers.removeAll();
this.discoverPendingUpdates.removeAll();
this.rawVisualizations.removeAll();
this.loadedVisualizations.removeAll();
}
const buildOverviewVisualizations = async (filterHandler, tab, subtab, localChange) => {
clearAll() {
this.clear();
this.tabVisualizations.removeAll();
}
async buildOverviewVisualizations(filterHandler, tab, subtab, localChange) {
try {
const data = await genericReq.request('GET',`/api/wazuh-elastic/create-vis/overview-${tab}/${appState.getCurrentPattern()}`)
rawVisualizations.assignItems(data.data.raw);
commonData.assignFilters(filterHandler, tab, localChange);
$rootScope.$emit('changeTabView',{tabView:subtab})
$rootScope.$broadcast('updateVis');
const data = await this.genericReq.request('GET',`/api/wazuh-elastic/create-vis/overview-${tab}/${this.appState.getCurrentPattern()}`)
this.rawVisualizations.assignItems(data.data.raw);
this.commonData.assignFilters(filterHandler, tab, localChange);
this.$rootScope.$emit('changeTabView',{tabView:subtab})
this.$rootScope.$broadcast('updateVis');
return;
} catch (error) {
return Promise.reject(error)
}
}
const buildAgentsVisualizations = async (filterHandler, tab, subtab, localChange, id) => {
async buildAgentsVisualizations(filterHandler, tab, subtab, localChange, id) {
try {
const data = await genericReq.request('GET',`/api/wazuh-elastic/create-vis/agents-${tab}/${appState.getCurrentPattern()}`)
rawVisualizations.assignItems(data.data.raw);
commonData.assignFilters(filterHandler, tab, localChange, id)
$rootScope.$emit('changeTabView',{tabView:subtab});
$rootScope.$broadcast('updateVis');
const data = await this.genericReq.request('GET',`/api/wazuh-elastic/create-vis/agents-${tab}/${this.appState.getCurrentPattern()}`)
this.rawVisualizations.assignItems(data.data.raw);
this.commonData.assignFilters(filterHandler, tab, localChange, id)
this.$rootScope.$emit('changeTabView',{tabView:subtab});
this.$rootScope.$broadcast('updateVis');
return;
} catch (error) {
return Promise.reject(error)
}
}
}
return {
clear,
clearAll,
buildOverviewVisualizations,
buildAgentsVisualizations
}
});
app.service('visFactoryService', VisFactoryService);

View File

@ -22,8 +22,7 @@
</div>
<div layout="row" class="wz-padding-top-10">
<p flex="50">Agents coverage</p>
<p ng-if="agentsCoverity" class="wz-text-right color-grey">{{(agentsCoverity | number:2)}}%</p>
<p ng-if="!agentsCoverity" class="wz-text-right color-grey">---</p>
<p class="wz-text-right color-grey">{{(agentsCoverity | number:2)}}%</p>
</div>
</div>
</div>

View File

@ -1,4 +1,4 @@
<div flex layout="column" ng-cloak ng-controller="managerController">
<div flex layout="column" ng-cloak ng-controller="managementController">
<!-- Top navbar section -->
<wz-menu ng-init="menuNavItem = 'manager'"></wz-menu>

View File

@ -0,0 +1,10 @@
include ./management.head
include ./welcome.html
include ./status.html
include ./configuration.html
include ./logs.html
include ./reporting.html
include ./monitoring/monitoring.jade
include ./groups/groups.html
include ./ruleset/ruleset.jade
include ../footer.foot

View File

@ -41,8 +41,7 @@
<div flex class="wz-text-truncatable">Never connected: <span class="wz-text-bold">{{agentsCountNeverConnected}}</span>
</div>
<div flex class="wz-text-truncatable">Agents coverage:
<span ng-if="agentsCoverity" class="wz-text-bold">{{(agentsCoverity | number:2)}}%</span>
<span ng-if="!agentsCoverity" class="wz-text-bold">---</span>
<span class="wz-text-bold">{{(agentsCoverity | number:2)}}%</span>
</div>
</md-card-content>
</md-card>

View File

@ -1,10 +0,0 @@
include ./manager.head
include ./manager-welcome.html
include ./manager-status.html
include ./manager-configuration.html
include ./manager-osseclog.html
include ./manager-reporting.html
include ./monitoring/monitoring.jade
include ./groups/groups.html
include ./ruleset/ruleset.jade
include ../footer.foot

View File

@ -41,13 +41,6 @@ const initLogger = () => {
*/
const initDirectory = async () => {
try{
if(!path.join(__dirname).includes('/usr/share/kibana') &&
path.join(__dirname).includes('plugins') &&
path.join(__dirname).includes('kibana')){
throw new Error('Kibana is out of /usr/share/kibana path and the Wazuh App is inside plugins directory')
}
if (!fs.existsSync(path.join(__dirname, '../../../optimize/wazuh-logs'))) {
fs.mkdirSync(path.join(__dirname, '../../../optimize/wazuh-logs'));
}