mirror of
https://github.com/valitydev/wazuh-kibana-app.git
synced 2024-11-06 09:55:18 +00:00
Merge branch '3.3' into 3.3-ciscat-extension
This commit is contained in:
commit
182ef33196
@ -14,7 +14,7 @@ import * as FileSaver from '../services/file-saver'
|
||||
|
||||
const app = uiModules.get('app/wazuh', []);
|
||||
|
||||
app.controller('agentsPreviewController', function ($scope, $routeParams, genericReq, apiReq, appState, $location, errorHandler, csvReq, shareAgent) {
|
||||
app.controller('agentsPreviewController', function ($scope, $routeParams, genericReq, appState, $location, errorHandler, csvReq, shareAgent) {
|
||||
|
||||
$scope.search = term => {
|
||||
$scope.$broadcast('wazuhSearch',{term})
|
||||
@ -50,36 +50,6 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
|
||||
$location.search('tab', $scope.submenuNavItem);
|
||||
});
|
||||
|
||||
let tmpUrl, tmpUrl2;
|
||||
if (appState.getClusterInfo().status === 'enabled') {
|
||||
tmpUrl = `/api/wazuh-elastic/top/cluster/${appState.getClusterInfo().cluster}/agent.name`;
|
||||
tmpUrl2 = `/api/wazuh-elastic/top/cluster/${appState.getClusterInfo().cluster}/agent.id`;
|
||||
} else {
|
||||
tmpUrl = `/api/wazuh-elastic/top/manager/${appState.getClusterInfo().manager}/agent.name`;
|
||||
tmpUrl2 = `/api/wazuh-elastic/top/manager/${appState.getClusterInfo().manager}/agent.id`;
|
||||
}
|
||||
|
||||
|
||||
// Retrieve os list
|
||||
const retrieveList = agents => {
|
||||
for(const agent of agents){
|
||||
if(agent.id === '000') continue;
|
||||
if(agent.group && !$scope.groups.includes(agent.group)) $scope.groups.push(agent.group);
|
||||
if(agent.node_name && !$scope.nodes.includes(agent.node_name)) $scope.nodes.push(agent.node_name);
|
||||
if(agent.version && !$scope.versions.includes(agent.version)) $scope.versions.push(agent.version);
|
||||
if(agent.os && agent.os.name){
|
||||
const exists = $scope.osPlatforms.filter((e) => e.name === agent.os.name && e.platform === agent.os.platform && e.version === agent.os.version);
|
||||
if(!exists.length){
|
||||
$scope.osPlatforms.push({
|
||||
name: agent.os.name,
|
||||
platform: agent.os.platform,
|
||||
version: agent.os.version
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$scope.downloadCsv = async () => {
|
||||
try {
|
||||
errorHandler.info('Your download should begin automatically...', 'CSV')
|
||||
@ -99,29 +69,35 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
|
||||
|
||||
const load = async () => {
|
||||
try{
|
||||
const api = JSON.parse(appState.getCurrentAPI()).id
|
||||
const clusterInfo = appState.getClusterInfo();
|
||||
const firstUrlParam = clusterInfo.status === 'enabled' ? 'cluster' : 'manager';
|
||||
const secondUrlParam = clusterInfo[firstUrlParam];
|
||||
|
||||
const data = await Promise.all([
|
||||
apiReq.request('GET', '/agents/summary', { }),
|
||||
genericReq.request('GET', tmpUrl)
|
||||
genericReq.request('GET', '/api/wazuh-api/agents-unique/' + api, {}),
|
||||
genericReq.request('GET', `/api/wazuh-elastic/top/${firstUrlParam}/${secondUrlParam}/agent.name`)
|
||||
]);
|
||||
|
||||
const unique = data[0].data.result;
|
||||
|
||||
|
||||
// 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.groups = unique.groups;
|
||||
$scope.nodes = unique.nodes;
|
||||
$scope.versions = unique.versions;
|
||||
$scope.osPlatforms = unique.osPlatforms;
|
||||
$scope.lastAgent = unique.lastAgent;
|
||||
$scope.agentsCountActive = unique.summary.agentsCountActive;
|
||||
$scope.agentsCountDisconnected = unique.summary.agentsCountDisconnected;
|
||||
$scope.agentsCountNeverConnected = unique.summary.agentsCountNeverConnected;
|
||||
$scope.agentsCountTotal = unique.summary.agentsCountTotal;
|
||||
$scope.agentsCoverity = unique.summary.agentsCoverity;
|
||||
|
||||
$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;
|
||||
|
||||
// tmpUrl y tmpUrl2
|
||||
if (data[1].data.data === '') {
|
||||
$scope.mostActiveAgent.name = appState.getClusterInfo().manager;
|
||||
$scope.mostActiveAgent.id = '000';
|
||||
} else {
|
||||
$scope.mostActiveAgent.name = data[1].data.data;
|
||||
const info = await genericReq.request('GET', tmpUrl2);
|
||||
const info = await genericReq.request('GET', `/api/wazuh-elastic/top/${firstUrlParam}/${secondUrlParam}/agent.id`);
|
||||
if (info.data.data === '' && $scope.mostActiveAgent.name !== '') {
|
||||
$scope.mostActiveAgent.id = '000';
|
||||
} else {
|
||||
@ -129,22 +105,6 @@ app.controller('agentsPreviewController', function ($scope, $routeParams, generi
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch agents sorting by -dateAdd and using pagination
|
||||
const agents = [];
|
||||
const total_items = data[0].data.data.Total;
|
||||
let offset = 0;
|
||||
const limit = 2000;
|
||||
while(agents.length < total_items){
|
||||
const page = await apiReq.request('GET', '/agents', { sort:'-dateAdd', limit, offset });
|
||||
agents.push(...page.data.data.items)
|
||||
offset += limit;
|
||||
}
|
||||
|
||||
// Last agent
|
||||
$scope.lastAgent = agents[0];
|
||||
|
||||
retrieveList(agents);
|
||||
|
||||
$scope.loading = false;
|
||||
if(!$scope.$$phase) $scope.$digest();
|
||||
return;
|
||||
|
@ -15,10 +15,11 @@ 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'
|
||||
|
||||
const app = uiModules.get('app/wazuh', []);
|
||||
|
||||
app.controller('agentsController', function ($timeout, $scope, $location, $rootScope, appState, apiReq, AgentsAutoComplete, errorHandler, tabVisualizations, vis2png, shareAgent, commonData, reportingService, visFactoryService) {
|
||||
app.controller('agentsController', function ($timeout, $scope, $location, $rootScope, appState, apiReq, AgentsAutoComplete, errorHandler, tabVisualizations, vis2png, shareAgent, commonData, reportingService, visFactoryService, csvReq) {
|
||||
|
||||
$rootScope.reportStatus = false;
|
||||
|
||||
@ -212,6 +213,23 @@ app.controller('agentsController', function ($timeout, $scope, $location, $rootS
|
||||
return;
|
||||
}
|
||||
|
||||
$scope.downloadCsv = async data_path => {
|
||||
try {
|
||||
errorHandler.info('Your download should begin automatically...', 'CSV')
|
||||
const currentApi = JSON.parse(appState.getCurrentAPI()).id;
|
||||
const output = await csvReq.fetch(data_path, currentApi, null);
|
||||
const blob = new Blob([output], {type: 'text/csv'});
|
||||
|
||||
FileSaver.saveAs(blob, 'packages.csv');
|
||||
|
||||
return;
|
||||
|
||||
} catch (error) {
|
||||
errorHandler.handle(error,'Download CSV');
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
//Destroy
|
||||
$scope.$on("$destroy", () => {
|
||||
|
@ -381,13 +381,17 @@ app.controller('settingsController', function ($scope, $rootScope, $http, $route
|
||||
};
|
||||
|
||||
// Toggle extension
|
||||
$scope.toggleExtension = async (extension, state) => {
|
||||
getCurrentAPIIndex()
|
||||
if ($scope.apiEntries && $scope.apiEntries.length && ['oscap','audit','pci','gdpr','ciscat','aws','virustotal'].includes(extension)) {
|
||||
$scope.apiEntries[currentApiEntryIndex]._source.extensions[extension] = state;
|
||||
appState.setExtensions($scope.apiEntries[currentApiEntryIndex]._id,$scope.apiEntries[currentApiEntryIndex]._source.extensions);
|
||||
|
||||
$scope.toggleExtension = (extension, state) => {
|
||||
try{
|
||||
const api = JSON.parse(appState.getCurrentAPI()).id
|
||||
const currentExtensions = appState.getExtensions(api);
|
||||
currentExtensions[extension] = state;
|
||||
appState.setExtensions(api,currentExtensions)
|
||||
getCurrentAPIIndex()
|
||||
$scope.apiEntries[currentApiEntryIndex]._source.extensions = currentExtensions;
|
||||
if(!$scope.$$phase) $scope.$digest();
|
||||
} catch (error) {
|
||||
errorHandler.handle(error, 'Settings')
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -24,7 +24,8 @@ app.directive('wazuhTable', function() {
|
||||
path: '=path',
|
||||
keys: '=keys',
|
||||
allowClick: '=allowClick',
|
||||
implicitFilter: '=implicitFilter'
|
||||
implicitFilter: '=implicitFilter',
|
||||
rowsPerPage: '=rowsPerPage'
|
||||
},
|
||||
controller: function($scope, apiReq, $timeout, shareAgent, $location, errorHandler) {
|
||||
$scope.keyEquivalence = KeyEquivalenece;
|
||||
@ -52,7 +53,7 @@ app.directive('wazuhTable', function() {
|
||||
|
||||
$scope.wazuh_table_loading = true;
|
||||
//// PAGINATION ////////////////////
|
||||
$scope.itemsPerPage = 10;
|
||||
$scope.itemsPerPage = $scope.rowsPerPage || 10;
|
||||
$scope.pagedItems = [];
|
||||
$scope.currentPage = 0;
|
||||
let items = [];
|
||||
@ -117,7 +118,9 @@ app.directive('wazuhTable', function() {
|
||||
instance.addSorting(field.value || field);
|
||||
$scope.sortValue = instance.sortValue;
|
||||
$scope.sortDir = instance.sortDir;
|
||||
items = await instance.fetch();
|
||||
const result = await instance.fetch();
|
||||
items = result.items;
|
||||
$scope.time = result.time;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
checkGap();
|
||||
@ -135,7 +138,9 @@ app.directive('wazuhTable', function() {
|
||||
$scope.wazuh_table_loading = true;
|
||||
if(removeFilters) instance.removeFilters();
|
||||
instance.addFilter('search',term);
|
||||
items = await instance.fetch();
|
||||
const result = await instance.fetch();
|
||||
items = result.items;
|
||||
$scope.time = result.time;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
checkGap();
|
||||
@ -160,7 +165,9 @@ app.directive('wazuhTable', function() {
|
||||
instance.addFilter(filter.name,filter.value);
|
||||
}
|
||||
|
||||
items = await instance.fetch();
|
||||
const result = await instance.fetch();
|
||||
items = result.items;
|
||||
$scope.time = result.time;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
checkGap();
|
||||
@ -194,13 +201,17 @@ app.directive('wazuhTable', function() {
|
||||
const realTimeFunction = async () => {
|
||||
try {
|
||||
while(realTime) {
|
||||
items = await instance.fetch({limit:10});
|
||||
await $timeout(1000);
|
||||
const result = await instance.fetch({limit:10});
|
||||
items = result.items;
|
||||
$scope.time = result.time;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
checkGap();
|
||||
$scope.searchTable();
|
||||
if(!$scope.$$phase) $scope.$digest()
|
||||
await $timeout(1000);
|
||||
}
|
||||
} catch(error) {
|
||||
realTime = false;
|
||||
@ -229,7 +240,9 @@ app.directive('wazuhTable', function() {
|
||||
const init = async () => {
|
||||
try {
|
||||
$scope.wazuh_table_loading = true;
|
||||
items = await instance.fetch();
|
||||
const result = await instance.fetch();
|
||||
items = result.items;
|
||||
$scope.time = result.time;
|
||||
$scope.totalItems = items.length;
|
||||
$scope.items = items;
|
||||
checkGap();
|
||||
@ -244,6 +257,23 @@ app.directive('wazuhTable', function() {
|
||||
|
||||
init()
|
||||
|
||||
const splitArray = array => {
|
||||
if(Array.isArray(array)){
|
||||
if(!array.length) return false;
|
||||
let str = '';
|
||||
for(const item of array) str += `${item}, `;
|
||||
str = str.substring(0, str.length - 2);
|
||||
return str;
|
||||
}
|
||||
return array;
|
||||
}
|
||||
|
||||
$scope.checkIfArray = item => {
|
||||
return typeof item === 'object' ?
|
||||
splitArray(item) :
|
||||
item == 0 ? '0' : item;
|
||||
}
|
||||
|
||||
$scope.$on('$destroy',() => {
|
||||
realTime = null;
|
||||
})
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
<div layout="row" class="md-padding" ng-show="wazuh_table_loading" >
|
||||
<md-progress-linear class="md-accent" md-mode="indeterminate"></md-progress-linear>
|
||||
<div class='uil-ring-css'><div></div></div>
|
||||
</div>
|
||||
<div layout="row" ng-show="!wazuh_table_loading && items.length">
|
||||
<table class="table table-striped table-condensed" style="table-layout: fixed !important" id="wz_table">
|
||||
@ -15,22 +15,31 @@
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr ng-class="allowClick ? 'cursor-pointer' : ''" class="wz-word-wrap" ng-repeat="item in pagedItems[currentPage]" ng-click="clickAction(item)">
|
||||
<td ng-repeat="key in keys" ng-if="path !== '/decoders'">{{ key === 'os.name' ? item.os.name || '---' : key === 'os.version' ? item.os.version || '---' : item[key.value || key] || '---' }}</td>
|
||||
<td ng-repeat="key in keys" ng-if="path !== '/decoders'">
|
||||
{{
|
||||
key === 'os.name' ?
|
||||
item.os.name || '---' :
|
||||
key === 'os.version' ?
|
||||
item.os.version || '---' :
|
||||
checkIfArray(item[key.value || key]) || '---'
|
||||
}}
|
||||
</td>
|
||||
<td ng-repeat="key in keys" ng-if="path === '/decoders'">
|
||||
{{
|
||||
key === 'details.program_name' || key.value === 'details.program_name' ?
|
||||
item.details.program_name || '---' :
|
||||
item.details.program_name || '---' :
|
||||
key === 'details.order' || key.value === 'details.order' ?
|
||||
item.details.order || '---' :
|
||||
item[key.value || key] || '---'
|
||||
item.details.order || '---' :
|
||||
checkIfArray(item[key.value || key]) || '---'
|
||||
}}
|
||||
</td>
|
||||
|
||||
</tr>
|
||||
</tbody>
|
||||
<tfoot ng-show="items.length >= itemsPerPage">
|
||||
<tfoot >
|
||||
<td colspan="{{keys.length}}">
|
||||
<div class="pagination pull-right" style="margin:0 !important">
|
||||
<span ng-show="!wazuh_table_loading" class="color-grey">{{ totalItems }} items ({{time | number: 2}} seconds)</span>
|
||||
<div ng-show="items.length >= itemsPerPage" class="pagination pull-right" style="margin:0 !important">
|
||||
<ul layout="row">
|
||||
<li ng-class="{disabled: currentPage == 0}" class="md-padding">
|
||||
<a href ng-click="prevPage()">« Prev</a>
|
||||
@ -50,6 +59,16 @@
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
<div layout="row" ng-show="!wazuh_table_loading" class="md-padding">
|
||||
Result: {{ totalItems }} items.
|
||||
|
||||
<div layout="row" ng-if="!wazuh_table_loading && !totalItems">
|
||||
<div flex class="euiCallOut euiCallOut--warning" data-test-subj="discoverNoResults">
|
||||
<div class="euiCallOutHeader">
|
||||
<svg class="euiIcon euiIcon--medium euiCallOutHeader__icon" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16" height="16" viewBox="0 0 16 16"><defs><path id="help-a" d="M13.6 12.186l-1.357-1.358c-.025-.025-.058-.034-.084-.056.53-.794.84-1.746.84-2.773a4.977 4.977 0 0 0-.84-2.772c.026-.02.059-.03.084-.056L13.6 3.813a6.96 6.96 0 0 1 0 8.373zM8 15A6.956 6.956 0 0 1 3.814 13.6l1.358-1.358c.025-.025.034-.057.055-.084C6.02 12.688 6.974 13 8 13a4.978 4.978 0 0 0 2.773-.84c.02.026.03.058.056.083l1.357 1.358A6.956 6.956 0 0 1 8 15zm-5.601-2.813a6.963 6.963 0 0 1 0-8.373l1.359 1.358c.024.025.057.035.084.056A4.97 4.97 0 0 0 3 8c0 1.027.31 1.98.842 2.773-.027.022-.06.031-.084.056l-1.36 1.358zm5.6-.187A4 4 0 1 1 8 4a4 4 0 0 1 0 8zM8 1c1.573 0 3.019.525 4.187 1.4l-1.357 1.358c-.025.025-.035.057-.056.084A4.979 4.979 0 0 0 8 3a4.979 4.979 0 0 0-2.773.842c-.021-.027-.03-.059-.055-.084L3.814 2.4A6.957 6.957 0 0 1 8 1zm0-1a8.001 8.001 0 1 0 .003 16.002A8.001 8.001 0 0 0 8 0z"></path></defs><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#help-a" fill-rule="evenodd"></use></svg>
|
||||
<span class="euiCallOutHeader__title">No results match your search criteria</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div layout="row" ng-if="!wazuh_table_loading && !totalItems" class="wz-margin-top-10">
|
||||
<span class="color-grey">0 items ({{time | number: 2}} seconds)</span>
|
||||
</div>
|
@ -56,6 +56,7 @@ export default class DataFactory {
|
||||
|
||||
async fetch(options = {}) {
|
||||
try {
|
||||
const start = new Date();
|
||||
this.items = [];
|
||||
let offset = 0;
|
||||
const limit = options.limit || 2000;
|
||||
@ -69,7 +70,9 @@ export default class DataFactory {
|
||||
this.items.push(...firstPage.data.data.items)
|
||||
if(options.limit) {
|
||||
if(this.path === '/agents') this.items = this.items.filter(item => item.id !== '000')
|
||||
return this.items;
|
||||
const end = new Date();
|
||||
const elapsed = (end - start) / 1000
|
||||
return {items:this.items, time:elapsed};
|
||||
}
|
||||
|
||||
const totalItems = firstPage.data.data.totalItems;
|
||||
@ -89,7 +92,11 @@ export default class DataFactory {
|
||||
const remainingItems = await Promise.all(ops);
|
||||
remainingItems.map(page => this.items.push(...page.data.data.items))
|
||||
if(this.path === '/agents') this.items = this.items.filter(item => item.id !== '000')
|
||||
return this.items;
|
||||
|
||||
const end = new Date();
|
||||
const elapsed = (end - start) / 1000;
|
||||
|
||||
return {items:this.items, time:elapsed};
|
||||
|
||||
} catch (error) {
|
||||
return Promise.reject(error);
|
||||
|
@ -101,7 +101,12 @@
|
||||
</div>
|
||||
|
||||
<div layout="row" class="margin-top-30">
|
||||
<wazuh-table flex path="'/agents'" keys="['id','name','ip','status','group','os.name','os.version','version']" allow-click="true">
|
||||
<wazuh-table
|
||||
flex
|
||||
path="'/agents'"
|
||||
keys="['id',{value:'name',size:2},'ip','status','group','os.name','os.version','version']"
|
||||
allow-click="true"
|
||||
rows-per-page="17">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
|
||||
|
@ -70,4 +70,10 @@
|
||||
keys="['name','architecture','version',{value:'vendor',size:3},{value:'description',size:3}]">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
<div layout="row" class="md-padding" ng-if="agent">
|
||||
<span flex></span>
|
||||
<a class="small" id="btnDownload" ng-click="downloadCsv('/syscollector/' + agent.id + '/packages')">Formatted
|
||||
<i aria-hidden="true" class="fa fa-fw fa-download"></i>
|
||||
</a>
|
||||
</div>
|
||||
</md-content>
|
@ -63,7 +63,12 @@
|
||||
|
||||
<!-- Groups table -->
|
||||
<div layout="row" ng-if="!lookingGroup" class="md-padding">
|
||||
<wazuh-table flex path="'/agents/groups'" keys="['name','count','merged_sum']" allow-click="true">
|
||||
<wazuh-table
|
||||
flex
|
||||
path="'/agents/groups'"
|
||||
keys="['name','count','merged_sum']"
|
||||
allow-click="true"
|
||||
rows-per-page="19">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
<!-- End groups table -->
|
||||
@ -79,8 +84,12 @@
|
||||
|
||||
<!-- Group agents table -->
|
||||
<div layout="row" ng-if="lookingGroup && groupsSelectedTab==='agents' && currentGroup" class="md-padding">
|
||||
<wazuh-table flex path="'/agents/groups/' + currentGroup.name" keys="['id','name','ip','status','os.name','os.version','version']"
|
||||
allow-click="true">
|
||||
<wazuh-table
|
||||
flex
|
||||
path="'/agents/groups/' + currentGroup.name"
|
||||
keys="['id','name','ip','status','os.name','os.version','version']"
|
||||
allow-click="true"
|
||||
rows-per-page="14">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
<!-- End Group agents table -->
|
||||
@ -96,8 +105,12 @@
|
||||
|
||||
<!-- Group files table -->
|
||||
<div layout="row" ng-if="lookingGroup && groupsSelectedTab==='files' && !fileViewer && currentGroup" class="md-padding">
|
||||
<wazuh-table flex path="'/agents/groups/' + currentGroup.name + '/files'" keys="[{value:'filename',size:2},{value:'hash',size:6}]"
|
||||
allow-click="true">
|
||||
<wazuh-table
|
||||
flex
|
||||
path="'/agents/groups/' + currentGroup.name + '/files'"
|
||||
keys="[{value:'filename',size:2},{value:'hash',size:6}]"
|
||||
allow-click="true"
|
||||
rows-per-page="14">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
<!-- End Group files table -->
|
||||
|
@ -48,7 +48,12 @@
|
||||
|
||||
<!-- Logs table section -->
|
||||
<div layout="row">
|
||||
<wazuh-table flex path="'/manager/logs'" keys="['timestamp',{value:'tag',size:2},'level',{value:'description',size:4,nosortable:true}]"></wazuh-table>
|
||||
<wazuh-table
|
||||
flex
|
||||
path="'/manager/logs'"
|
||||
keys="['timestamp',{value:'tag',size:2},'level',{value:'description',size:4,nosortable:true}]"
|
||||
rows-per-page="19">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
<!-- End Logs table section -->
|
||||
|
||||
|
@ -47,13 +47,15 @@
|
||||
flex
|
||||
path="'/decoders'"
|
||||
keys="['name',{value:'details.program_name',size:2},{value:'details.order',size:2},'file']"
|
||||
allow-click="true">
|
||||
allow-click="true"
|
||||
rows-per-page="18">
|
||||
</wazuh-table>
|
||||
<wazuh-table ng-if="!implicitFilterFromDetail"
|
||||
flex
|
||||
path="'/decoders'"
|
||||
keys="['name',{value:'details.program_name',size:2,nosortable:true},{value:'details.order',size:2,nosortable:true},'file']"
|
||||
allow-click="true">
|
||||
allow-click="true"
|
||||
rows-per-page="18">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
|
||||
|
@ -55,12 +55,16 @@
|
||||
implicit-filter="implicitFilterFromDetail"
|
||||
flex
|
||||
path="'/rules'"
|
||||
keys="['id',{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},'level']" allow-click="true">
|
||||
keys="['id',{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},'level']"
|
||||
allow-click="true"
|
||||
rows-per-page="18">
|
||||
</wazuh-table>
|
||||
<wazuh-table ng-if="!implicitFilterFromDetail"
|
||||
flex
|
||||
path="'/rules'"
|
||||
keys="['id',{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},'level']" allow-click="true">
|
||||
keys="['id',{value:'file',size:2},{value:'description',size:2},{value:'groups',nosortable:true,size:2},{value:'pci',nosortable:true,size:2},{value:'gdpr',nosortable:true},'level']"
|
||||
allow-click="true"
|
||||
rows-per-page="18">
|
||||
</wazuh-table>
|
||||
</div>
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
height: 300px;
|
||||
color: black;
|
||||
direction: ltr;
|
||||
border-top: 1px solid #ddd
|
||||
}
|
||||
|
||||
/* PADDING */
|
||||
@ -281,6 +282,7 @@ div.CodeMirror span.CodeMirror-nonmatchingbracket {color: #a22;}
|
||||
|
||||
.CodeMirror-code {
|
||||
outline: none;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
||||
/* Force content-box sizing for the elements where we expect it */
|
||||
|
@ -757,4 +757,93 @@ export default class WazuhApi {
|
||||
}
|
||||
}
|
||||
|
||||
async getAgentsFieldsUniqueCount(req, reply) {
|
||||
try {
|
||||
|
||||
if(!req.params || !req.params.api) throw new Error('Field api is required')
|
||||
|
||||
const config = await this.wzWrapper.getWazuhConfigurationById(req.params.api);
|
||||
|
||||
const headers = {
|
||||
headers: {
|
||||
'wazuh-app-version': packageInfo.version
|
||||
},
|
||||
username : config.user,
|
||||
password : config.password,
|
||||
rejectUnauthorized: !config.insecure
|
||||
};
|
||||
|
||||
const url = `${config.url}:${config.port}/agents`;
|
||||
|
||||
const params = {
|
||||
limit : 2000,
|
||||
offset: 0,
|
||||
sort :'-dateAdd'
|
||||
}
|
||||
|
||||
const items = [];
|
||||
|
||||
const output = await needle('get', url, params, headers)
|
||||
|
||||
items.push(...output.body.data.items)
|
||||
|
||||
const totalItems = output.body.data.totalItems;
|
||||
|
||||
while(items.length < totalItems){
|
||||
params.offset += params.limit;
|
||||
const tmp = await needle('get', url, params, headers)
|
||||
items.push(...tmp.body.data.items)
|
||||
}
|
||||
|
||||
const result = {
|
||||
groups : [],
|
||||
nodes : [],
|
||||
versions : [],
|
||||
osPlatforms: [],
|
||||
lastAgent : items[0],
|
||||
summary: {
|
||||
agentsCountActive :0,
|
||||
agentsCountDisconnected :0,
|
||||
agentsCountNeverConnected:0,
|
||||
agentsCountTotal :0,
|
||||
agentsCoverity :0
|
||||
}
|
||||
}
|
||||
|
||||
for(const agent of items){
|
||||
if(agent.id === '000') continue;
|
||||
if(agent.group && !result.groups.includes(agent.group)) result.groups.push(agent.group);
|
||||
if(agent.node_name && !result.nodes.includes(agent.node_name)) result.nodes.push(agent.node_name);
|
||||
if(agent.version && !result.versions.includes(agent.version)) result.versions.push(agent.version);
|
||||
if(agent.os && agent.os.name){
|
||||
const exists = result.osPlatforms.filter((e) => e.name === agent.os.name && e.platform === agent.os.platform && e.version === agent.os.version);
|
||||
if(!exists.length){
|
||||
result.osPlatforms.push({
|
||||
name: agent.os.name,
|
||||
platform: agent.os.platform,
|
||||
version: agent.os.version
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const summary = await needle('get', url + '/summary', {}, headers)
|
||||
|
||||
// Once Wazuh core fixes agent 000 issues, this should be adjusted
|
||||
const active = summary.body.data.Active - 1;
|
||||
const total = summary.body.data.Total - 1;
|
||||
|
||||
result.summary.agentsCountActive = active;
|
||||
result.summary.agentsCountDisconnected = summary.body.data.Disconnected;
|
||||
result.summary.agentsCountNeverConnected = summary.body.data['Never connected'];
|
||||
result.summary.agentsCountTotal = total;
|
||||
result.summary.agentsCoverity = (active / total) * 100;
|
||||
|
||||
return reply({error:0, result})
|
||||
|
||||
} catch (error) {
|
||||
return ErrorResponse(error.message || error, 3035, 500, reply)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -57,4 +57,6 @@ export default (server, options) => {
|
||||
// Returns total RAM available from the current machine where Kibana is being executed
|
||||
server.route({ method: 'GET', path: '/api/wazuh-api/ram', handler: (req,res) => ctrl.totalRam(req,res)})
|
||||
|
||||
// Returns unique fields from the agents such OS, agent version ...
|
||||
server.route({ method: 'GET', path: '/api/wazuh-api/agents-unique/{api}', handler: (req,res) => ctrl.getAgentsFieldsUniqueCount(req,res)});
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user