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

989 lines
28 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-09-10 08:32:49 +00:00
import needle from 'needle';
2018-09-11 09:52:54 +00:00
import { pciRequirementsFile } from '../integration-files/pci-requirements';
import { gdprRequirementsFile } from '../integration-files/gdpr-requirements';
2018-09-10 08:32:49 +00:00
import { ElasticWrapper } from '../lib/elastic-wrapper';
import { getPath } from '../../util/get-path';
import packageInfo from '../../package.json';
import { Monitoring } from '../monitoring';
import { ErrorResponse } from './error-response';
import { Parser } from 'json2csv';
2018-09-03 09:46:55 +00:00
import { getConfiguration } from '../lib/get-configuration';
2018-09-10 08:32:49 +00:00
import { log } from '../logger';
2018-09-11 09:52:54 +00:00
import { KeyEquivalenece } from '../../util/csv-key-equivalence';
import { cleanKeys } from '../../util/remove-key';
import { apiRequestList } from '../../util/api-request-list'
2018-07-16 09:35:46 +00:00
2018-09-03 09:46:55 +00:00
export class WazuhApiCtrl {
2018-09-10 08:32:49 +00:00
constructor(server) {
this.wzWrapper = new ElasticWrapper(server);
this.fetchAgentsExternal = Monitoring(server, { disableCron: true });
}
async checkStoredAPI(req, reply) {
try {
// Get config from elasticsearch
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(
req.payload
);
if (wapi_config.error_code > 1) {
throw new Error(`Could not find Wazuh API entry on Elasticsearch.`);
} else if (wapi_config.error_code > 0) {
throw new Error(
'Valid credentials not found in Elasticsearch. It seems the credentials were not saved.'
);
}
2018-10-15 10:34:33 +00:00
const credInfo = {
headers: {
'wazuh-app-version': packageInfo.version
},
username: wapi_config.user,
password: wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
};
2018-09-10 08:32:49 +00:00
let response = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/version`,
{},
2018-10-15 10:34:33 +00:00
credInfo
2018-09-10 08:32:49 +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-10-15 10:34:33 +00:00
credInfo
2018-09-10 08:32:49 +00:00
);
if (!response.body.error) {
2018-10-15 10:34:33 +00:00
try {
const managerInfo = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/agents/000`,
{},
credInfo
);
const updatedManagerName = managerInfo.body.data.name;
wapi_config.cluster_info.manager = updatedManagerName;
await this.wzWrapper.updateWazuhIndexDocument(req.payload, {
doc: { cluster_info: wapi_config.cluster_info }
});
} catch (error) {
log(
'POST /api/check-stored-api :: Error updating Wazuh manager name.',
error.message || error
);
}
2018-09-10 08:32:49 +00:00
// If cluster mode is active
if (response.body.data.enabled === 'yes') {
response = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/cluster/node`,
{},
2018-10-15 10:34:33 +00:00
credInfo
2018-09-10 08:32:49 +00:00
);
if (!response.body.error) {
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 = '****';
return reply({
statusCode: 200,
data: wapi_config,
idChanged: req.idChanged || null
});
} else if (response.body.error) {
const tmpMsg =
response && response.body && response.body.message
? response.body.message
: 'Unexpected error from /cluster/node';
throw new Error(tmpMsg);
2018-03-22 16:10:33 +00:00
}
2018-09-10 08:32:49 +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-09-10 08:32:49 +00:00
return reply({
statusCode: 200,
data: wapi_config,
idChanged: req.idChanged || null
});
}
} else {
const tmpMsg =
response && response.body && response.body.message
? response.body.message
: 'Unexpected error from /cluster/status';
2018-09-10 08:32:49 +00:00
throw new Error(tmpMsg);
}
2018-09-10 08:32:49 +00:00
} else {
if (
response &&
response.body &&
response.body.error &&
response.body.message
) {
throw new Error(response.body.message);
}
2017-10-27 08:05:27 +00:00
2018-09-10 08:32:49 +00:00
throw new Error(
`${wapi_config.url}:${wapi_config.port}/version is unreachable`
);
}
} catch (error) {
if (error.code === 'ECONNREFUSED') {
2018-10-01 07:56:50 +00:00
log('POST /api/check-stored-api', error.message || error);
2018-09-10 08:32:49 +00:00
return reply({
statusCode: 200,
data: { password: '****', apiIsDown: true }
});
} else {
// Check if we can connect to a different API
if (
error &&
error.body &&
typeof error.body.found !== 'undefined' &&
!error.body.found
) {
try {
const apis = await this.wzWrapper.getWazuhAPIEntries();
for (const api of apis.hits.hits) {
try {
const response = await needle(
'get',
`${api._source.url}:${api._source.api_port}/version`,
{},
{
2018-06-11 11:32:01 +00:00
headers: {
2018-09-10 08:32:49 +00:00
'wazuh-app-version': packageInfo.version
2018-06-11 11:32:01 +00:00
},
2018-09-10 08:32:49 +00:00
username: api._source.api_user,
password: Buffer.from(
api._source.api_password,
'base64'
).toString('ascii'),
rejectUnauthorized: !api._source.insecure
}
);
if (
response &&
response.body &&
response.body.error === 0 &&
response.body.data
) {
req.payload = api._id;
req.idChanged = api._id;
return this.checkStoredAPI(req, reply);
2018-03-22 14:50:42 +00:00
}
} catch (error) { } // eslint-disable-line
}
2018-09-10 08:32:49 +00:00
} catch (error) {
2018-10-01 07:56:50 +00:00
log('POST /api/check-stored-api', error.message || error);
2018-09-10 08:32:49 +00:00
return ErrorResponse(error.message || error, 3020, 500, reply);
}
2018-03-22 14:50:42 +00:00
}
2018-10-01 07:56:50 +00:00
log('POST /api/check-stored-api', error.message || error);
2018-09-10 08:32:49 +00:00
return ErrorResponse(error.message || error, 3002, 500, reply);
}
}
2018-09-10 08:32:49 +00:00
}
2016-10-25 19:54:05 +00:00
2018-09-10 08:32:49 +00:00
validateCheckApiParams(payload) {
if (!('user' in payload)) {
return 'Missing param: API USER';
2018-05-14 10:56:27 +00:00
}
2018-09-10 08:32:49 +00:00
if (!('password' in payload) && !('id' in payload)) {
return 'Missing param: API PASSWORD';
}
2018-09-10 08:32:49 +00:00
if (!('url' in payload)) {
return 'Missing param: API URL';
}
2018-05-14 10:56:27 +00:00
2018-09-10 08:32:49 +00:00
if (!('port' in payload)) {
return 'Missing param: API PORT';
}
2018-05-14 10:56:27 +00:00
2018-09-10 08:32:49 +00:00
if (!payload.url.includes('https://') && !payload.url.includes('http://')) {
return 'protocol_error';
}
2018-05-14 10:56:27 +00:00
2018-09-10 08:32:49 +00:00
return false;
}
async checkAPI(req, reply) {
try {
let apiAvailable = null;
const notValid = this.validateCheckApiParams(req.payload);
if (notValid) return ErrorResponse(notValid, 3003, 500, reply);
// Check if a Wazuh API id is given (already stored API)
if (req.payload && req.payload.id && !req.payload.password) {
const data = await this.wzWrapper.getWazuhConfigurationById(
req.payload.id
);
if (data) apiAvailable = data;
else
return ErrorResponse(
`The API ${req.payload.id} was not found`,
3029,
500,
reply
);
// Check if a password is given
} else if (req.payload && req.payload.password) {
apiAvailable = req.payload;
apiAvailable.password = Buffer.from(
req.payload.password,
'base64'
).toString('ascii');
}
let response = await needle(
'get',
`${apiAvailable.url}:${apiAvailable.port}/version`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
username: apiAvailable.user,
password: apiAvailable.password,
rejectUnauthorized: !apiAvailable.insecure
}
);
// Check wrong credentials
if (parseInt(response.statusCode) === 401) {
return ErrorResponse('Wrong credentials', 3004, 500, reply);
}
if (parseInt(response.body.error) === 0 && response.body.data) {
response = await needle(
'get',
`${apiAvailable.url}:${apiAvailable.port}/agents/000`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
username: apiAvailable.user,
password: apiAvailable.password,
rejectUnauthorized: !apiAvailable.insecure
}
);
if (!response.body.error) {
const managerName = response.body.data.name;
response = await needle(
'get',
`${apiAvailable.url}:${apiAvailable.port}/cluster/status`,
{},
{
// Checking the cluster status
headers: {
'wazuh-app-version': packageInfo.version
},
username: apiAvailable.user,
password: apiAvailable.password,
rejectUnauthorized: !apiAvailable.insecure
}
);
if (!response.body.error) {
if (response.body.data.enabled === 'yes') {
// If cluster mode is active
response = await needle(
'get',
`${apiAvailable.url}:${apiAvailable.port}/cluster/node`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
username: apiAvailable.user,
password: apiAvailable.password,
rejectUnauthorized: !apiAvailable.insecure
2018-05-14 10:56:27 +00:00
}
2018-09-10 08:32:49 +00:00
);
2018-05-14 10:56:27 +00:00
2018-09-10 08:32:49 +00:00
if (!response.body.error) {
2018-05-14 10:56:27 +00:00
return reply({
2018-09-10 08:32:49 +00:00
manager: managerName,
node: response.body.data.node,
cluster: response.body.data.cluster,
status: 'enabled'
2018-05-14 10:56:27 +00:00
});
2018-09-10 08:32:49 +00:00
}
} else {
// Cluster mode is not active
return reply({
manager: managerName,
cluster: 'Disabled',
status: 'disabled'
});
2018-05-14 10:56:27 +00:00
}
2018-09-10 08:32:49 +00:00
}
2017-10-27 08:05:27 +00:00
}
2018-09-10 08:32:49 +00:00
}
const tmpMsg =
response.body && response.body.message
? response.body.message
: 'Unexpected error checking the Wazuh API';
throw new Error(tmpMsg);
} catch (error) {
2018-10-01 07:56:50 +00:00
log('POST /api/check-api', error.message || error);
2018-09-10 08:32:49 +00:00
return ErrorResponse(error.message || error, 3005, 500, reply);
}
2018-09-10 08:32:49 +00:00
}
2018-09-10 08:32:49 +00:00
async getPciRequirement(req, reply) {
try {
let pci_description = '';
2016-10-25 19:54:05 +00:00
2018-09-10 08:32:49 +00:00
if (req.params.requirement === 'all') {
if (!req.headers.id) {
return reply(pciRequirementsFile);
2018-03-22 16:10:33 +00:00
}
2018-09-10 08:32:49 +00:00
let wapi_config = await this.wzWrapper.getWazuhConfigurationById(
req.headers.id
);
if (wapi_config.error_code > 1) {
// Can not connect to elasticsearch
return ErrorResponse(
'Elasticsearch unexpected error or cannot connect',
3007,
400,
reply
);
} else if (wapi_config.error_code > 0) {
// Credentials not found
return ErrorResponse('Credentials does not exists', 3008, 400, reply);
}
2018-09-10 08:32:49 +00:00
const response = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/rules/pci`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
username: wapi_config.user,
password: wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
}
);
if (response.body.data && response.body.data.items) {
let PCIobject = {};
for (let item of response.body.data.items) {
if (typeof pciRequirementsFile[item] !== 'undefined')
PCIobject[item] = pciRequirementsFile[item];
}
return reply(PCIobject);
2016-10-25 19:54:05 +00:00
} else {
2018-09-10 08:32:49 +00:00
return ErrorResponse(
'An error occurred trying to parse PCI DSS requirements',
3009,
400,
reply
);
2016-10-25 19:54:05 +00:00
}
2018-09-10 08:32:49 +00:00
} else {
if (
typeof pciRequirementsFile[req.params.requirement] !== 'undefined'
) {
pci_description = pciRequirementsFile[req.params.requirement];
}
2017-06-01 15:08:10 +00:00
2018-09-10 08:32:49 +00:00
return reply({
pci: {
requirement: req.params.requirement,
description: pci_description
}
});
}
} catch (error) {
return ErrorResponse(error.message || error, 3010, 400, reply);
}
2018-09-10 08:32:49 +00:00
}
2018-09-10 08:32:49 +00:00
async getGdprRequirement(req, reply) {
try {
let gdpr_description = '';
2018-09-10 08:32:49 +00:00
if (req.params.requirement === 'all') {
if (!req.headers.id) {
return reply(gdprRequirementsFile);
}
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(
req.headers.id
);
// Checking for GDPR
const version = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/version`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
username: wapi_config.user,
password: wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
}
);
const number = version.body.data;
const major = number.split('v')[1].split('.')[0];
const minor = number
.split('v')[1]
.split('.')[1]
.split('.')[0];
const patch = number
.split('v')[1]
.split('.')[1]
.split('.')[1];
if (
(major >= 3 && minor < 2) ||
(major >= 3 && minor >= 2 && patch < 3)
) {
return reply({});
}
2018-09-10 08:32:49 +00:00
if (wapi_config.error_code > 1) {
// Can not connect to elasticsearch
return ErrorResponse(
'Elasticsearch unexpected error or cannot connect',
3024,
400,
reply
);
} else if (wapi_config.error_code > 0) {
// Credentials not found
return ErrorResponse('Credentials does not exists', 3025, 400, reply);
}
2018-09-10 08:32:49 +00:00
const response = await needle(
'get',
`${wapi_config.url}:${wapi_config.port}/rules/gdpr`,
{},
{
headers: {
'wazuh-app-version': packageInfo.version
},
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 {
return ErrorResponse(
'An error occurred trying to parse GDPR requirements',
3026,
400,
reply
);
}
} else {
if (
typeof gdprRequirementsFile[req.params.requirement] !== 'undefined'
) {
gdpr_description = gdprRequirementsFile[req.params.requirement];
}
2018-09-10 08:32:49 +00:00
return reply({
gdpr: {
requirement: req.params.requirement,
description: gdpr_description
}
});
}
} catch (error) {
return ErrorResponse(error.message || error, 3027, 400, reply);
}
}
async makeRequest(method, path, data, id, reply) {
try {
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(id);
if (wapi_config.error_code > 1) {
//Can not connect to elasticsearch
return ErrorResponse(
'Could not connect with elasticsearch',
3011,
404,
reply
);
} else if (wapi_config.error_code > 0) {
//Credentials not found
return ErrorResponse('Credentials does not exists', 3012, 404, reply);
}
if (!data) {
data = {};
}
const options = {
headers: {
'wazuh-app-version': packageInfo.version
},
username: wapi_config.user,
password: wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
};
const fullUrl = getPath(wapi_config) + path;
const response = await needle(method, fullUrl, data, options);
if (
response &&
response.body &&
!response.body.error &&
response.body.data
) {
cleanKeys(response);
2018-09-10 08:32:49 +00:00
return reply(response.body);
}
throw response &&
response.body &&
response.body.error &&
response.body.message
2018-09-28 13:23:47 +00:00
? { message: response.body.message, code: response.body.error }
2018-09-10 08:32:49 +00:00
: new Error('Unexpected error fetching data from the Wazuh API');
} catch (error) {
2018-09-28 13:23:47 +00:00
return ErrorResponse(
error.message || error,
`Wazuh API error: ${error.code}` || 3013,
500,
reply
);
2018-06-01 07:51:24 +00:00
}
2018-09-10 08:32:49 +00:00
}
async makeGenericRequest(method, path, data, id) {
try {
const wapi_config = await this.wzWrapper.getWazuhConfigurationById(id);
if (wapi_config.error_code > 1) {
//Can not connect to elasticsearch
throw new Error('Could not connect with elasticsearch');
} else if (wapi_config.error_code > 0) {
//Credentials not found
throw new Error('Credentials does not exists');
}
if (!data) {
data = {};
}
const options = {
headers: {
'wazuh-app-version': packageInfo.version
},
username: wapi_config.user,
password: wapi_config.password,
rejectUnauthorized: !wapi_config.insecure
};
const fullUrl = getPath(wapi_config) + path;
const response = await needle(method, fullUrl, data, options);
if (
response &&
response.body &&
!response.body.error &&
response.body.data
) {
cleanKeys(response);
2018-09-10 08:32:49 +00:00
return response.body;
}
throw response &&
response.body &&
response.body.error &&
response.body.message
2018-09-28 13:23:47 +00:00
? { message: response.body.message, code: response.body.error }
2018-09-10 08:32:49 +00:00
: new Error('Unexpected error fetching data from the Wazuh API');
} catch (error) {
return Promise.reject(error);
}
}
requestApi(req, reply) {
2018-10-30 13:21:00 +00:00
const configuration = getConfiguration();
2018-11-15 08:39:12 +00:00
const adminMode = !(configuration && typeof configuration.admin !== 'undefined' && !configuration.admin);
2018-09-10 08:32:49 +00:00
if (!req.payload.method) {
return ErrorResponse('Missing param: method', 3015, 400, reply);
} else if (!req.payload.path) {
return ErrorResponse('Missing param: path', 3016, 400, reply);
} else {
if (
req.payload.method !== 'GET' &&
req.payload.body &&
req.payload.body.devTools
) {
2018-10-30 13:21:00 +00:00
if (!adminMode) {
2018-09-10 08:32:49 +00:00
return ErrorResponse('Allowed method: [GET]', 3029, 400, reply);
}
}
if (req.payload.body.devTools) {
delete req.payload.body.devTools;
const keyRegex = new RegExp(/.*agents\/\d*\/key.*/);
if (
typeof req.payload.path === 'string' &&
2018-10-30 13:21:00 +00:00
keyRegex.test(req.payload.path) &&
!adminMode
2018-09-10 08:32:49 +00:00
) {
return ErrorResponse(
'Forbidden route /agents/<id>/key',
3028,
400,
reply
);
}
2018-09-10 08:32:49 +00:00
}
return this.makeRequest(
req.payload.method,
req.payload.path,
req.payload.body,
req.payload.id,
reply
);
}
2018-09-10 08:32:49 +00:00
}
// Fetch agent status and insert it directly on demand
async fetchAgents(req, reply) {
try {
const output = await this.fetchAgentsExternal();
return reply({
statusCode: 200,
error: '0',
data: '',
output
});
} catch (error) {
return ErrorResponse(error.message || error, 3018, 500, reply);
}
}
/**
* Get full data on CSV format from a list Wazuh API endpoint
* @param {*} req
* @param {*} res
*/
async csv(req, reply) {
try {
if (!req.payload || !req.payload.path)
throw new Error('Field path is required');
if (!req.payload.id) throw new Error('Field id is required');
const filters =
req.payload && req.payload.filters && Array.isArray(req.payload.filters)
? req.payload.filters
: [];
const config = await this.wzWrapper.getWazuhConfigurationById(
req.payload.id
);
let path_tmp = req.payload.path;
if (path_tmp && typeof path_tmp === 'string') {
path_tmp = path_tmp[0] === '/' ? path_tmp.substr(1) : path_tmp;
}
if (!path_tmp) throw new Error('An error occurred parsing path field');
// Real limit, regardless the user query
const params = { limit: 1000 };
if (filters.length) {
for (const filter of filters) {
if (!filter.name || !filter.value) continue;
params[filter.name] = filter.value;
}
}
const cred = {
headers: {
'wazuh-app-version': packageInfo.version
},
username: config.user,
password: config.password,
rejectUnauthorized: !config.insecure
};
const itemsArray = [];
const output = await needle(
'get',
`${config.url}:${config.port}/${path_tmp}`,
params,
cred
);
if (
output &&
output.body &&
output.body.data &&
output.body.data.totalItems
) {
params.offset = 0;
const { totalItems } = output.body.data;
itemsArray.push(...output.body.data.items);
while (itemsArray.length < totalItems) {
params.offset += params.limit;
const tmpData = await needle(
'get',
`${config.url}:${config.port}/${path_tmp}`,
params,
cred
);
itemsArray.push(...tmpData.body.data.items);
}
}
if (
output &&
output.body &&
output.body.data &&
output.body.data.totalItems
) {
2018-11-27 11:03:29 +00:00
const fields = req.payload.path.includes('/agents')
? [
'id',
'status',
'name',
'ip',
'group',
'manager',
'node_name',
'dateAdd',
'version',
'lastKeepAlive',
'os'
]
: Object.keys(output.body.data.items[0]);
2018-09-10 08:32:49 +00:00
const json2csvParser = new Parser({ fields });
let csv = json2csvParser.parse(itemsArray);
for (const field of fields) {
if (csv.includes(field)) {
2018-09-11 09:52:54 +00:00
csv = csv.replace(field, KeyEquivalenece[field] || field);
2018-09-10 08:32:49 +00:00
}
}
2018-09-10 08:32:49 +00:00
return reply(csv).type('text/csv');
} else if (
output &&
output.body &&
output.body.data &&
!output.body.data.totalItems
) {
throw new Error('No results');
} else {
throw new Error('An error occurred fetching data from the Wazuh API');
}
} catch (error) {
return ErrorResponse(error.message || error, 3034, 500, reply);
}
}
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
};
2018-10-22 14:51:20 +00:00
const distinctUrl = `${config.url}:${config.port}/agents/stats/distinct`;
2018-09-10 08:32:49 +00:00
const data = await Promise.all([
needle(
'get',
2018-10-22 14:51:20 +00:00
distinctUrl,
2018-09-10 08:32:49 +00:00
{ fields: 'node_name', select: 'node_name' },
headers
),
needle(
'get',
`${config.url}:${config.port}/agents/groups`,
{},
2018-09-10 08:32:49 +00:00
headers
),
needle(
'get',
2018-10-22 14:51:20 +00:00
distinctUrl,
2018-09-10 08:32:49 +00:00
{
fields: 'os.name,os.platform,os.version',
select: 'os.name,os.platform,os.version'
},
headers
),
needle(
'get',
2018-10-22 14:51:20 +00:00
distinctUrl,
2018-09-10 08:32:49 +00:00
{ fields: 'version', select: 'version' },
headers
),
needle(
'get',
`${config.url}:${config.port}/agents/summary`,
{},
headers
),
needle(
'get',
`${config.url}:${config.port}/agents`,
{ limit: 1, sort: '-dateAdd' },
headers
)
]);
2018-10-22 14:51:20 +00:00
const parsedResponses = data.map(
item =>
2018-11-27 11:03:29 +00:00
item && item.body && item.body.data && !item.body.error
? item.body.data
: false
2018-10-22 14:51:20 +00:00
);
const [
nodes,
groups,
osPlatforms,
versions,
summary,
lastAgent
] = parsedResponses;
2018-09-10 08:32:49 +00:00
const result = {
groups: [],
nodes: [],
versions: [],
osPlatforms: [],
lastAgent: {},
summary: {
agentsCountActive: 0,
agentsCountDisconnected: 0,
agentsCountNeverConnected: 0,
agentsCountTotal: 0,
agentsCoverity: 0
2018-07-17 07:41:53 +00:00
}
2018-09-10 08:32:49 +00:00
};
2018-10-22 14:51:20 +00:00
if (nodes && nodes.items) {
result.nodes = nodes.items
2018-09-10 08:32:49 +00:00
.filter(item => !!item.node_name)
.map(item => item.node_name);
}
2018-10-22 14:51:20 +00:00
if (groups && groups.items) {
result.groups = groups.items.map(item => item.name);
2018-09-10 08:32:49 +00:00
}
2018-10-22 14:51:20 +00:00
if (osPlatforms && osPlatforms.items) {
result.osPlatforms = osPlatforms.items
2018-09-10 08:32:49 +00:00
.filter(
item =>
!!item.os && item.os.platform && item.os.name && item.os.version
)
.map(item => item.os);
}
2018-10-22 14:51:20 +00:00
if (versions && versions.items) {
result.versions = versions.items
2018-09-10 08:32:49 +00:00
.filter(item => !!item.version)
.map(item => item.version);
}
2018-10-22 14:51:20 +00:00
if (summary) {
2018-09-10 08:32:49 +00:00
Object.assign(result.summary, {
2018-10-22 14:51:20 +00:00
agentsCountActive: summary.Active - 1,
agentsCountDisconnected: summary.Disconnected,
agentsCountNeverConnected: summary['Never connected'],
agentsCountTotal: summary.Total - 1,
2018-09-10 08:32:49 +00:00
agentsCoverity:
2018-10-22 14:51:20 +00:00
summary.Total - 1
? ((summary.Active - 1) / (summary.Total - 1)) * 100
2018-09-10 08:32:49 +00:00
: 0
});
}
2018-10-22 14:51:20 +00:00
if (lastAgent && lastAgent.items && lastAgent.items.length) {
Object.assign(result.lastAgent, lastAgent.items[0]);
2018-09-10 08:32:49 +00:00
}
return reply({ error: 0, result });
} catch (error) {
return ErrorResponse(error.message || error, 3035, 500, reply);
2018-07-17 07:41:53 +00:00
}
2018-09-10 08:32:49 +00:00
}
// Get de list of available requests in the API
getRequestList(req, reply) {
//Read a static JSON until the api call has implemented
return reply(apiRequestList);
}
}