wazuh-kibana-app/server/controllers/wazuh-api.js

670 lines
27 KiB
JavaScript
Raw Normal View History

/*
* Wazuh app - Class for Wazuh-API functions
* 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.
*/
// Require some libraries
2018-04-22 13:41:10 +00:00
import needle from 'needle'
import path from 'path'
import colors from 'ansicolors'
import pciRequirementsFile from '../integration-files/pci-requirements'
2018-05-14 10:56:27 +00:00
import gdprRequirementsFile from '../integration-files/gdpr-requirements'
2018-04-22 13:41:10 +00:00
import ElasticWrapper from '../lib/elastic-wrapper'
import getPath from '../../util/get-path'
import packageInfo from '../../package.json'
import monitoring from '../monitoring'
2018-04-30 15:12:55 +00:00
import ErrorResponse from './error-response'
import { Parser } from 'json2csv';
import getConfiguration from '../lib/get-configuration'
2018-05-30 09:00:06 +00:00
import PDFDocument from 'pdfkit'
import fs from 'fs'
2018-05-30 14:14:00 +00:00
import descriptions from '../reporting/tab-description'
import * as TimSort from 'timsort'
2018-05-30 14:14:00 +00:00
import { AgentsVisualizations, OverviewVisualizations, ClusterVisualizations } from '../integration-files/visualizations'
const blueWazuh = colors.blue('wazuh');
2017-10-20 18:53:56 +00:00
2018-04-22 13:41:10 +00:00
export default class WazuhApi {
constructor(server){
this.wzWrapper = new ElasticWrapper(server);
2018-04-22 13:41:10 +00:00
this.fetchAgentsExternal = monitoring(server,{disableCron:true})
}
2017-01-26 15:35:07 +00:00
async checkStoredAPI (req, reply) {
2018-03-22 16:10:33 +00:00
try{
2018-04-30 15:12:55 +00:00
if(!protectedRoute(req)) return ErrorResponse('Session expired', 3001, 401, reply);
2018-03-22 16:10:33 +00:00
// Get config from elasticsearch
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(req.payload)
2017-10-20 18:53:56 +00:00
if (wapi_config.error_code > 1) {
throw new Error(`Could not find Wazuh API entry on Elasticsearch.`)
2017-10-20 18:53:56 +00:00
} else if (wapi_config.error_code > 0) {
throw new Error('Valid credentials not found in Elasticsearch. It seems the credentials were not saved.')
2017-10-20 18:53:56 +00:00
}
2018-03-22 16:10:33 +00:00
let response = await needle('get', `${wapi_config.url}:${wapi_config.port}/version`, {}, {
username : wapi_config.user,
password : wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
})
2018-03-22 16:10:33 +00:00
if (parseInt(response.body.error) === 0 && response.body.data) {
// Checking the cluster status
response = await needle('get', `${wapi_config.url}:${wapi_config.port}/cluster/status`, {}, {
2018-03-22 16:10:33 +00:00
username : wapi_config.user,
password : wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
})
if (!response.body.error) {
// If cluster mode is active
if (response.body.data.enabled === 'yes') {
2018-03-22 16:10:33 +00:00
response = await needle('get', `${wapi_config.url}:${wapi_config.port}/cluster/node`, {}, {
username : wapi_config.user,
password : wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
})
if (!response.body.error) {
2018-03-22 16:10:33 +00:00
let managerName = wapi_config.cluster_info.manager;
delete wapi_config.cluster_info;
wapi_config.cluster_info = {};
wapi_config.cluster_info.status = 'enabled';
wapi_config.cluster_info.manager = managerName;
wapi_config.cluster_info.node = response.body.data.node;
wapi_config.cluster_info.cluster = response.body.data.cluster;
wapi_config.password = '****'
2018-03-22 16:10:33 +00:00
return reply({ statusCode: 200, data: wapi_config });
} else if (response.body.error){
2018-05-14 10:56:27 +00:00
const tmpMsg = response && response.body && response.body.message ?
response.body.message :
2018-04-30 15:12:55 +00:00
'Unexpected error from /cluster/node';
2018-05-14 10:56:27 +00:00
2018-04-30 15:12:55 +00:00
throw new Error(tmpMsg)
}
2018-03-22 16:10:33 +00:00
} else { // Cluster mode is not active
let managerName = wapi_config.cluster_info.manager;
delete wapi_config.cluster_info;
wapi_config.cluster_info = {};
wapi_config.cluster_info.status = 'disabled';
wapi_config.cluster_info.cluster = 'Disabled';
wapi_config.cluster_info.manager = managerName;
wapi_config.password = '****'
2018-03-22 16:10:33 +00:00
2018-04-30 15:12:55 +00:00
return reply({ statusCode: 200, data: wapi_config });
2018-03-22 16:10:33 +00:00
}
2018-04-30 15:12:55 +00:00
} else {
2018-05-14 10:56:27 +00:00
const tmpMsg = response && response.body && response.body.message ?
response.body.message :
2018-04-30 15:12:55 +00:00
'Unexpected error from /cluster/status';
throw new Error(tmpMsg)
}
2018-03-22 16:10:33 +00:00
} else {
2018-04-30 15:12:55 +00:00
throw new Error(`${wapi_config.url}:${wapi_config.port}/version is unreachable`)
2018-03-22 16:10:33 +00:00
}
} catch(error){
if(error.code === 'ECONNREFUSED'){
return reply({ statusCode: 200, data: {password: '****', apiIsDown: true } });
2018-03-22 16:10:33 +00:00
} else {
2018-04-30 15:12:55 +00:00
return ErrorResponse(error.message || error, 3002, 500, reply);
2018-03-22 16:10:33 +00:00
}
}
}
2017-06-01 15:08:10 +00:00
validateCheckApiParams (payload) {
2018-03-22 14:50:42 +00:00
if (!('user' in payload)) {
2018-04-30 15:12:55 +00:00
return 'Missing param: API USER';
}
2018-03-22 14:50:42 +00:00
if (!('password' in payload)) {
2018-04-30 15:12:55 +00:00
return 'Missing param: API PASSWORD';
}
2018-03-22 14:50:42 +00:00
if (!('url' in payload)) {
2018-04-30 15:12:55 +00:00
return 'Missing param: API URL';
}
2018-03-22 14:50:42 +00:00
if (!('port' in payload)) {
2018-04-30 15:12:55 +00:00
return 'Missing param: API PORT';
}
2018-03-22 14:50:42 +00:00
if (!(payload.url.includes('https://')) && !(payload.url.includes('http://'))) {
2018-04-30 15:12:55 +00:00
return 'protocol_error';
}
2017-10-27 08:05:27 +00:00
2018-03-22 14:50:42 +00:00
return false;
}
async checkAPI (req, reply) {
2018-03-22 14:50:42 +00:00
try {
const notValid = this.validateCheckApiParams(req.payload);
2018-05-14 10:56:27 +00:00
if(notValid) return ErrorResponse(notValid, 3003, 500, reply);
2018-03-22 14:50:42 +00:00
req.payload.password = Buffer.from(req.payload.password, 'base64').toString('ascii');
2018-03-22 14:50:42 +00:00
let response = await needle('get', `${req.payload.url}:${req.payload.port}/version`, {}, {
username : req.payload.user,
password : req.payload.password,
rejectUnauthorized: !req.payload.insecure
})
// Check wrong credentials
if(parseInt(response.statusCode) === 401){
2018-04-30 15:12:55 +00:00
return ErrorResponse('Wrong credentials', 3004, 500, reply);
}
if (parseInt(response.body.error) === 0 && response.body.data) {
2018-03-22 14:50:42 +00:00
response = await needle('get', `${req.payload.url}:${req.payload.port}/agents/000`, {}, {
username : req.payload.user,
password : req.payload.password,
rejectUnauthorized: !req.payload.insecure
})
2018-03-22 14:50:42 +00:00
if (!response.body.error) {
const managerName = response.body.data.name;
2018-03-22 14:50:42 +00:00
response = await needle('get', `${req.payload.url}:${req.payload.port}/cluster/status`, {}, { // Checking the cluster status
username : req.payload.user,
password : req.payload.password,
rejectUnauthorized: !req.payload.insecure
})
if (!response.body.error) {
if (response.body.data.enabled === 'yes') {
2018-03-22 14:50:42 +00:00
// If cluster mode is active
response = await needle('get', `${req.payload.url}:${req.payload.port}/cluster/node`, {}, {
username : req.payload.user,
password : req.payload.password,
rejectUnauthorized: !req.payload.insecure
})
if (!response.body.error) {
2018-03-22 14:50:42 +00:00
return reply({
manager: managerName,
node : response.body.data.node,
cluster: response.body.data.cluster,
status : 'enabled'
});
}
} else {
2018-03-22 14:50:42 +00:00
// Cluster mode is not active
return reply({
manager: managerName,
cluster: 'Disabled',
status : 'disabled'
});
}
}
2018-03-22 14:50:42 +00:00
}
}
2018-05-14 10:56:27 +00:00
const tmpMsg = response.body && response.body.message ?
response.body.message :
2018-04-30 15:12:55 +00:00
'Unexpected error checking the Wazuh API';
2018-04-30 15:12:55 +00:00
throw new Error(tmpMsg)
2018-03-22 14:50:42 +00:00
} catch(error) {
2018-04-30 15:12:55 +00:00
return ErrorResponse(error.message || error, 3005, 500, reply);
2018-03-22 14:50:42 +00:00
}
}
2016-10-25 19:54:05 +00:00
async getPciRequirement (req, reply) {
2017-10-20 18:53:56 +00:00
try {
2018-04-30 15:12:55 +00:00
if(!protectedRoute(req)) return ErrorResponse('Session expired', 3006, 401, reply);
2018-04-18 16:07:44 +00:00
let pci_description = '';
if (req.params.requirement === 'all') {
if(!req.headers.id) {
2018-04-18 16:07:44 +00:00
return reply(pciRequirementsFile);
}
let wapi_config = await this.wzWrapper.getWazuhConfigurationById(req.headers.id);
2018-03-22 16:10:33 +00:00
if (wapi_config.error_code > 1) {
// Can not connect to elasticsearch
2018-05-14 10:56:27 +00:00
return ErrorResponse('Elasticsearch unexpected error or cannot connect', 3007, 400, reply);
2018-03-22 16:10:33 +00:00
} else if (wapi_config.error_code > 0) {
// Credentials not found
2018-05-14 10:56:27 +00:00
return ErrorResponse('Credentials does not exists', 3008, 400, reply);
2018-03-22 16:10:33 +00:00
}
2018-03-22 16:10:33 +00:00
const response = await needle('get', `${wapi_config.url}:${wapi_config.port}/rules/pci`, {}, {
username : wapi_config.user,
password : wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
})
2018-03-22 16:10:33 +00:00
if(response.body.data && response.body.data.items){
let PCIobject = {};
for(let item of response.body.data.items){
2018-04-18 16:07:44 +00:00
if(typeof pciRequirementsFile[item] !== 'undefined') PCIobject[item] = pciRequirementsFile[item];
2018-03-22 16:10:33 +00:00
}
return reply(PCIobject);
} else {
2018-05-14 10:56:27 +00:00
return ErrorResponse('An error occurred trying to parse PCI DSS requirements', 3009, 400, reply);
2018-03-22 16:10:33 +00:00
}
} else {
2018-04-18 16:07:44 +00:00
if (typeof pciRequirementsFile[req.params.requirement] !== 'undefined'){
pci_description = pciRequirementsFile[req.params.requirement];
}
return reply({
pci: {
requirement: req.params.requirement,
description: pci_description
}
});
}
2018-03-22 14:50:42 +00:00
} catch (error) {
2018-05-14 10:56:27 +00:00
return ErrorResponse(error.message || error, 3010, 400, reply);
}
}
async getGdprRequirement (req, reply) {
try {
2018-05-15 15:42:04 +00:00
if(!protectedRoute(req)) return ErrorResponse('Session expired', 3023, 401, reply);
2018-05-14 10:56:27 +00:00
2018-05-17 11:58:31 +00:00
// Prevents load GDPR if it's disabled
const configFile = getConfiguration();
if(configFile && typeof configFile['extensions.gdpr'] !== 'undefined' && !configFile['extensions.gdpr']) {
return reply({});
}
2018-05-14 10:56:27 +00:00
let gdpr_description = '';
if (req.params.requirement === 'all') {
if(!req.headers.id) {
return reply(gdprRequirementsFile);
}
let wapi_config = await this.wzWrapper.getWazuhConfigurationById(req.headers.id);
if (wapi_config.error_code > 1) {
// Can not connect to elasticsearch
2018-05-15 15:42:04 +00:00
return ErrorResponse('Elasticsearch unexpected error or cannot connect', 3024, 400, reply);
2018-05-14 10:56:27 +00:00
} else if (wapi_config.error_code > 0) {
// Credentials not found
2018-05-15 15:42:04 +00:00
return ErrorResponse('Credentials does not exists', 3025, 400, reply);
2018-05-14 10:56:27 +00:00
}
const response = await needle('get', `${wapi_config.url}:${wapi_config.port}/rules/gdpr`, {}, {
username : wapi_config.user,
password : wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
})
if(response.body.data && response.body.data.items){
let GDPRobject = {};
for(let item of response.body.data.items){
if(typeof gdprRequirementsFile[item] !== 'undefined') GDPRobject[item] = gdprRequirementsFile[item];
}
return reply(GDPRobject);
} else {
2018-05-15 15:42:04 +00:00
return ErrorResponse('An error occurred trying to parse GDPR requirements', 3026, 400, reply);
2018-05-14 10:56:27 +00:00
}
} else {
if (typeof gdprRequirementsFile[req.params.requirement] !== 'undefined'){
gdpr_description = gdprRequirementsFile[req.params.requirement];
}
return reply({
gdpr: {
requirement: req.params.requirement,
description: gdpr_description
}
});
}
} catch (error) {
2018-05-15 15:42:04 +00:00
return ErrorResponse(error.message || error, 3027, 400, reply);
2017-10-27 08:05:27 +00:00
}
2016-10-25 19:54:05 +00:00
}
async makeRequest (method, path, data, id, reply) {
2018-03-22 16:10:33 +00:00
try {
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(id);
2018-03-22 16:10:33 +00:00
2016-10-25 19:54:05 +00:00
if (wapi_config.error_code > 1) {
//Can not connect to elasticsearch
2018-05-14 10:56:27 +00:00
return ErrorResponse('Could not connect with elasticsearch', 3011, 404, reply);
2016-10-25 19:54:05 +00:00
} else if (wapi_config.error_code > 0) {
//Credentials not found
2018-05-14 10:56:27 +00:00
return ErrorResponse('Credentials does not exists', 3012, 404, reply);
2016-10-25 19:54:05 +00:00
}
if (!data) {
data = {};
}
2016-10-25 19:54:05 +00:00
2018-03-22 14:50:42 +00:00
const options = {
headers: {
'wazuh-app-version': packageInfo.version
},
2018-03-22 16:10:33 +00:00
username : wapi_config.user,
password : wapi_config.password,
2016-10-25 19:54:05 +00:00
rejectUnauthorized: !wapi_config.insecure
};
2018-03-22 16:10:33 +00:00
const fullUrl = getPath(wapi_config) + path;
const response = await needle(method, fullUrl, data, options);
2017-10-27 08:05:27 +00:00
if(response && response.body && !response.body.error && response.body.data) {
return reply(response.body)
}
2018-03-22 16:10:33 +00:00
throw response && response.body && response.body.error && response.body.message ?
new Error(response.body.message) :
new Error('Unexpected error fetching data from the Wazuh API')
2018-05-14 10:56:27 +00:00
2018-03-22 16:10:33 +00:00
} catch (error) {
2018-05-14 10:56:27 +00:00
return ErrorResponse(error.message || error, 3013, 500, reply);
2018-03-22 16:10:33 +00:00
}
}
2016-10-25 19:54:05 +00:00
requestApi (req, reply) {
2018-04-30 15:12:55 +00:00
if(!protectedRoute(req)) return ErrorResponse('Session expired', 3014, 401, reply);
2016-10-25 19:54:05 +00:00
if (!req.payload.method) {
2018-05-14 10:56:27 +00:00
return ErrorResponse('Missing param: method', 3015, 400, reply);
2016-10-25 19:54:05 +00:00
} else if (!req.payload.path) {
2018-05-14 10:56:27 +00:00
return ErrorResponse('Missing param: path', 3016, 400, reply);
2016-10-25 19:54:05 +00:00
} else {
if(req.payload.method !== 'GET' && req.payload.body && req.payload.body.devTools){
const configuration = getConfiguration();
if(!configuration || (configuration && !configuration['devtools.allowall'])){
2018-05-14 10:56:27 +00:00
return ErrorResponse('Allowed method: [GET]', 3023, 400, reply);
}
}
2018-05-18 10:16:00 +00:00
if(req.payload.body.devTools) {
delete req.payload.body.devTools;
const keyRegex = new RegExp(/.*agents\/\d*\/key.*/)
if(typeof req.payload.path === 'string' && keyRegex.test(req.payload.path)){
return ErrorResponse('Forbidden route /agents/<id>/key', 3028, 400, reply);
}
}
return this.makeRequest(req.payload.method, req.payload.path, req.payload.body, req.payload.id, reply);
2016-10-25 19:54:05 +00:00
}
}
2016-10-25 19:54:05 +00:00
// Fetch agent status and insert it directly on demand
async fetchAgents (req, reply) {
try{
2018-04-30 15:12:55 +00:00
if(!protectedRoute(req)) return ErrorResponse('Session expired', 3017, 401, reply);
const output = await this.fetchAgentsExternal();
return reply({
'statusCode': 200,
'error': '0',
'data': '',
output
});
} catch(error){
2018-05-14 10:56:27 +00:00
return ErrorResponse(error.message || error, 3018, 500, reply);
}
}
2017-06-01 15:08:10 +00:00
getConfigurationFile (req,reply) {
try{
const configFile = getConfiguration();
if(configFile && configFile['login.password']){
delete configFile['login.password'];
}
return reply({
statusCode: 200,
2018-03-22 14:50:42 +00:00
error : 0,
data : configFile || {}
});
2018-03-22 14:50:42 +00:00
} catch (error) {
2018-05-14 10:56:27 +00:00
return ErrorResponse(error.message || error, 3019, 500, reply);
}
}
login(req,reply) {
try{
const configFile = getConfiguration();
2018-03-22 14:50:42 +00:00
if(!configFile){
2018-03-22 14:50:42 +00:00
throw new Error('Configuration file not found');
}
2018-03-22 14:50:42 +00:00
if(!req.payload.password) {
2018-05-14 10:56:27 +00:00
return ErrorResponse('Please give me a password.', 3020, 401, reply);
} else if(req.payload.password !== configFile['login.password']){
2018-05-14 10:56:27 +00:00
return ErrorResponse('Wrong password, please try again.', 3021, 401, reply);
}
2018-03-22 14:50:42 +00:00
const code = (new Date()-1) + 'wazuhapp';
2018-03-22 14:50:42 +00:00
sessions[code] = {
created: new Date(),
exp : 86400
}
2018-03-22 14:50:42 +00:00
return reply({ statusCode: 200, error: 0, code });
} catch (error) {
2018-05-14 10:56:27 +00:00
return ErrorResponse(error.message || error, 3022, 500, reply);
}
}
/**
* Get full data on CSV format from a list Wazuh API endpoint
2018-05-14 10:56:27 +00:00
* @param {*} req
* @param {*} res
*/
async csv(req,res) {
try{
2018-05-14 10:56:27 +00:00
if(!req.payload || !req.payload.path) throw new Error('Field path is required')
if(!req.payload.id) throw new Error('Field id is required')
2018-04-30 11:19:50 +00:00
const filters = req.payload && req.payload.filters && Array.isArray(req.payload.filters) ?
req.payload.filters :
[];
2018-05-14 10:56:27 +00:00
const config = await this.wzWrapper.getWazuhConfigurationById(req.payload.id)
let path = req.payload.path;
if(path && typeof path === 'string'){
path = path[0] === '/' ? path.substr(1) : path
}
2018-05-14 10:56:27 +00:00
if(!path) throw new Error('An error occurred parsing path field')
2018-05-14 10:56:27 +00:00
2018-04-30 11:19:50 +00:00
const params = { limit: 99999 };
if(filters.length) {
for(const filter of filters) {
if(!filter.name || !filter.value) continue;
params[filter.name] = filter.value;
}
}
2018-04-30 11:19:50 +00:00
const output = await needle('get', `${config.url}:${config.port}/${path}`, params, {
username : config.user,
password : config.password,
rejectUnauthorized: !config.insecure
})
if(output && output.body && output.body.data && output.body.data.totalItems) {
const fields = Object.keys(output.body.data.items[0]);
const data = output.body.data.items;
const json2csvParser = new Parser({ fields });
2018-05-14 10:56:27 +00:00
const csv = json2csvParser.parse(data);
2018-05-14 10:56:27 +00:00
return res({ csv });
2018-05-14 10:56:27 +00:00
} else if (output && output.body && output.body.data && !output.body.data.totalItems) {
2018-05-14 10:56:27 +00:00
throw new Error('No results')
2018-05-14 10:56:27 +00:00
} else {
throw new Error('An error occurred fetching data from the Wazuh API')
2018-05-14 10:56:27 +00:00
}
} catch (error) {
return res({ error: error.message || error }).code(500)
}
}
async report(req,reply) {
try {
2018-05-30 09:00:06 +00:00
if (!fs.existsSync(path.join(__dirname, '../../../wazuh-reporting'))) {
fs.mkdirSync(path.join(__dirname, '../../../wazuh-reporting'));
}
2018-05-30 09:00:06 +00:00
if(req.payload && req.payload.array){
2018-05-30 09:00:06 +00:00
const doc = new PDFDocument();
doc.pipe(fs.createWriteStream(path.join(__dirname, '../../../wazuh-reporting/' + req.payload.name)));
2018-05-29 15:43:04 +00:00
doc.image(path.join(__dirname, '../../public/img/logo.png'),410,20,{fit:[150,70]})
doc.moveDown().fontSize(9).fillColor('blue').text('https://wazuh.com',442,50,{link: 'https://wazuh.com', underline:true, valign:'right', align: 'right'})
2018-05-30 09:00:06 +00:00
2018-05-30 14:14:00 +00:00
const tab = req.payload.tab;
const section = req.payload.section;
if(req.payload.section && typeof req.payload.section === 'string') {
doc.fontSize(18).fillColor('black').text(descriptions[tab].title + ' report',45,70)
2018-05-29 15:43:04 +00:00
doc.moveDown()
}
if(req.payload.time){
const str = `${req.payload.time.from} to ${req.payload.time.to}`
2018-05-30 14:14:00 +00:00
const currentY = doc.y;
const currentX = doc.x;
doc.fontSize(10).image(path.join(__dirname, '../reporting/clock.png'),currentX,currentY,{width:8, height:8}).text(str,currentX+10,currentY)
2018-05-29 15:43:04 +00:00
doc.moveDown()
}
2018-05-30 09:00:06 +00:00
2018-05-29 15:43:04 +00:00
if(req.payload.filters) {
2018-05-30 14:14:00 +00:00
doc.x -= 10;
2018-05-29 15:43:04 +00:00
let str = '';
const len = req.payload.filters.length;
for(let i=0; i < len; i++) {
const filter = req.payload.filters[i];
str += i === len - 1 ?
filter.meta.key + ': ' + filter.meta.value :
filter.meta.key + ': ' + filter.meta.value + ' AND '
}
2018-05-30 14:14:00 +00:00
const currentY = doc.y;
const currentX = doc.x;
doc.fontSize(10).image(path.join(__dirname, '../reporting/filters.png'),currentX,currentY,{width:8, height:8}).text(str,currentX+10,currentY)
2018-05-29 15:43:04 +00:00
doc.moveDown()
2018-05-30 14:14:00 +00:00
doc.x -= 10;
2018-05-29 15:43:04 +00:00
}
2018-05-30 14:14:00 +00:00
doc.fontSize(12).text(descriptions[tab].description)
doc.moveDown()
doc.moveDown()
let counter = 0;
2018-05-30 14:14:00 +00:00
let maxWidth = 0;
for(const item of req.payload.array){
2018-05-30 14:14:00 +00:00
if(item.width > maxWidth) maxWidth = item.width;
}
const scaleFactor = 530 / maxWidth;
let pageNumber = 0;
doc.on('pageAdded', () => pageNumber++);
const len = req.payload.array.length;
for(let i = 0; i < len; i++){
const item = req.payload.array[i]
const title = req.payload.isAgents ?
AgentsVisualizations[tab].filter(v => v._id === item.id) :
OverviewVisualizations[tab].filter(v => v._id === item.id);
counter++;
2018-05-30 14:14:00 +00:00
doc.fontSize(12).text(title[0]._source.title)
doc.moveDown()
doc.image(item.element,((doc.page.width - (item.width*scaleFactor)) / 2),doc.y,{ align: 'center', scale: scaleFactor });
2018-05-30 09:00:06 +00:00
doc.moveDown()
2018-05-30 14:14:00 +00:00
doc.moveDown()
if(counter >= 3 || counter === 2 && pageNumber === 0) {
2018-05-29 15:43:04 +00:00
doc.fontSize(7).text('Copyright © 2018 Wazuh, Inc.', 440, doc.page.height - 30, {
lineBreak: false
})
2018-05-30 14:14:00 +00:00
if(i !== (len - 1)) doc.addPage();
counter = 0;
}
}
2018-05-30 09:00:06 +00:00
2018-05-29 15:43:04 +00:00
doc.fontSize(7).text('Copyright © 2018 Wazuh, Inc.', 440, doc.page.height - 30, {
lineBreak: false
})
2018-05-30 09:00:06 +00:00
doc.end();
}
return reply({error: 0, data: null})
} catch (error) {
return ErrorResponse(error.message || error, 3029, 500, reply);
}
}
async getReports(req,reply) {
try {
const list = [];
const reportDir = path.join(__dirname, '../../../wazuh-reporting');
const sortFunction = (a,b) => a.date < b.date ? 1 : a.date > b.date ? -1 : 0;
fs.readdirSync(reportDir).forEach(file => {
const stats = fs.statSync(reportDir + '/' + file);
file = {
name: file,
size: stats.size,
date: stats.birthtime
}
list.push(file)
})
TimSort.sort(list,sortFunction)
return reply({list: list});
} catch (error) {
return ErrorResponse(error.message || error, 3031, 500, reply);
}
}
async getReportByName(req,reply) {
try {
return reply.file(path.join(__dirname, '../../../wazuh-reporting/' + req.params.name));
} catch (error) {
return ErrorResponse(error.message || error, 3030, 500, reply);
}
}
async deleteReportByName(req,reply) {
try {
fs.unlinkSync(path.join(__dirname, '../../../wazuh-reporting/' + req.params.name))
return reply({error:0})
} catch (error) {
return ErrorResponse(error.message || error, 3032, 500, reply);
}
}
}