mirror of
https://github.com/valitydev/wazuh-kibana-app.git
synced 2024-11-06 18:05:20 +00:00
268 lines
11 KiB
JavaScript
268 lines
11 KiB
JavaScript
module.exports = function (server, options) {
|
|
|
|
// Colors for console logging
|
|
const colors = require('ansicolors');
|
|
const blueWazuh = colors.blue('wazuh');
|
|
|
|
const client = server.plugins.elasticsearch.client;
|
|
var index_pattern = "wazuh-alerts-*";
|
|
var index_prefix = "wazuh-alerts-";
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
const KIBANA_FIELDS_FILE = '../scripts/integration_files/kibana_fields_file.json';
|
|
var kibana_fields_data = {};
|
|
|
|
const payloads = {
|
|
getFieldTop: { "size": 1, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": '', "size": 1, "order": { "_count": "desc" } } } } },
|
|
getLastField: { "size": 1, "query": { "bool": { "must": [{ "exists": { "field": '' } }, { "query_string": { "query": "*" } }], "must_not": [{}] } }, "sort": [{ "@timestamp": { "order": "desc", "unmapped_type": "boolean" } }] },
|
|
statsOverviewAlerts: [{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": {} },
|
|
{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": "srcip", "size": 1, "order": { "_count": "desc" } } } } },
|
|
{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": "rule.groups", "size": 1, "order": { "_count": "desc" } } } } }],
|
|
statsOverviewSyscheck: [{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "rule.groups:syscheck", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": {} },
|
|
{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "rule.groups:syscheck", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": "AgentName", "size": 1, "order": { "_count": "desc" } } } } },
|
|
{ "size": 0, "query": { "bool": { "must": [{ "query_string": { "query": "*", "analyze_wildcard": true } }, { "range": { "@timestamp": { "gte": '', "format": "epoch_millis" } } }], "must_not": [] } }, "aggs": { "2": { "terms": { "field": "SyscheckFile.path", "size": 1, "order": { "_count": "desc" } } } } }]
|
|
};
|
|
|
|
//Handlers
|
|
|
|
var fetchElastic = function (payload) {
|
|
return client.search({ index: 'wazuh-alerts-*', type: 'wazuh', body: payload });
|
|
};
|
|
|
|
var getFieldTop = function (req, reply) {
|
|
var filtering = false;
|
|
|
|
// is date defined? or must use 24h ?
|
|
var date = new Date();
|
|
date.setDate(date.getDate() - 1);
|
|
date = date.getTime();
|
|
|
|
const timeAgo = req.params.time ? encodeURIComponent(req.params.time) : date;
|
|
|
|
if (req.params.fieldValue && req.params.fieldFilter)
|
|
filtering = true;
|
|
|
|
var payload = JSON.parse(JSON.stringify(payloads.getFieldTop));
|
|
|
|
if (req.params.fieldFilter && req.params.fieldFilter2) {
|
|
payload.query.bool.must[0].query_string.query = req.params.fieldFilter + ":" + req.params.fieldValue + " AND " + req.params.fieldFilter2 + ":" + req.params.fieldValue2 + " AND host: " + req.params.manager;
|
|
}else if(req.params.fieldFilter){
|
|
payload.query.bool.must[0].query_string.query = req.params.fieldFilter + ":" + req.params.fieldValue + " AND host: " + req.params.manager;
|
|
}else{
|
|
payload.query.bool.must[0].query_string.query = "host: " + req.params.manager;
|
|
}
|
|
|
|
console.log(payload.query.bool.must[0].query_string.query);
|
|
console.log(req.params);
|
|
payload.query.bool.must[1].range['@timestamp'].gte = timeAgo;
|
|
payload.aggs['2'].terms.field = req.params.field;
|
|
|
|
|
|
fetchElastic(payload).then(function (data) {
|
|
|
|
if (data.hits.total == 0 || typeof data.aggregations['2'].buckets[0] === 'undefined')
|
|
reply({ 'statusCode': 200, 'data': '' });
|
|
else
|
|
reply({ 'statusCode': 200, 'data': data.aggregations['2'].buckets[0].key });
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
};
|
|
|
|
var getLastField = function (req, reply) {
|
|
var filtering = false;
|
|
var filterArray = {};
|
|
var termArray = {};
|
|
|
|
if (req.params.fieldValue && req.params.fieldFilter)
|
|
filtering = true;
|
|
|
|
var payload = JSON.parse(JSON.stringify(payloads.getLastField));
|
|
payload.query.bool.must[0].exists.field = req.params.field;
|
|
|
|
filterArray["host"] = req.params.manager;
|
|
termArray = { "term": filterArray };
|
|
payload.query.bool.must.push(termArray);
|
|
filterArray = {};
|
|
termArray = {};
|
|
|
|
if (filtering) {
|
|
filterArray[req.params.fieldFilter] = req.params.fieldValue;
|
|
termArray = { "term": filterArray };
|
|
payload.query.bool.must.push(termArray);
|
|
}
|
|
|
|
fetchElastic(payload).then(function (data) {
|
|
|
|
if (data.hits.total == 0 || typeof data.hits.hits[0] === 'undefined')
|
|
reply({ 'statusCode': 200, 'data': '' });
|
|
else
|
|
reply({ 'statusCode': 200, 'data': data.hits.hits[0]._source[req.params.field] });
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
};
|
|
|
|
var statsOverviewAlerts = function (req, reply) {
|
|
var gte = new Date() - (24 * 3600);
|
|
|
|
var _payloads = payloads.statsOverviewAlerts;
|
|
|
|
var _data = [];
|
|
|
|
_payloads[0].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
_payloads[1].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
_payloads[2].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
|
|
fetchElastic(_payloads[0]).then(function (data) {
|
|
_data['alerts'] = data.hits.total;
|
|
fetchElastic(_payloads[1]).then(function (data) {
|
|
if (data.hits.total == 0)
|
|
_data['ip'] = '-';
|
|
else
|
|
_data['ip'] = data.aggregations['2'].buckets[0].key;
|
|
fetchElastic(_payloads[2]).then(function (data) {
|
|
if (data.hits.total == 0)
|
|
_data['group'] = '-';
|
|
else
|
|
_data['group'] = data.aggregations['2'].buckets[0].key;
|
|
reply({ 'statusCode': 200, 'data': { 'alerts': _data['alerts'], 'ip': _data['ip'], 'group': _data['group'] } });
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
};
|
|
|
|
var statsOverviewSyscheck = function (req, reply) {
|
|
var gte = new Date() - (24 * 3600);
|
|
|
|
var _payloads = payloads.statsOverviewSyscheck;
|
|
|
|
var _data = [];
|
|
|
|
_payloads[0].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
_payloads[1].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
_payloads[2].query.bool.must[1].range['@timestamp'].gte = gte;
|
|
|
|
fetchElastic(_payloads[0]).then(function (data) {
|
|
data['alerts'] = data.hits.total;
|
|
fetchElastic(_payloads[1]).then(function (data) {
|
|
if (data.hits.total == 0)
|
|
_data['agent'] = '-';
|
|
else
|
|
_data['agent'] = data.aggregations['2'].buckets[0].key;
|
|
fetchElastic(_payloads[2]).then(function (data) {
|
|
if (data.hits.total == 0)
|
|
_data['file'] = '-';
|
|
else
|
|
_data['file'] = data.aggregations['2'].buckets[0].key;
|
|
reply({ 'statusCode': 200, 'data': { 'alerts': _data['alerts'], 'agent': _data['agent'], 'file': _data['file'] } });
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
}, function () {
|
|
reply({ 'statusCode': 500, 'error': 9, 'message': 'Could not get data from elasticsearch' }).code(500);
|
|
});
|
|
};
|
|
|
|
var putWazuhPattern = function (req, reply) {
|
|
|
|
try {
|
|
kibana_fields_data = JSON.parse(fs.readFileSync(path.resolve(__dirname, KIBANA_FIELDS_FILE), 'utf8'));
|
|
} catch (e) {
|
|
server.log([blueWazuh, 'initialize', 'error'], 'Could not read the mapping file.');
|
|
server.log([blueWazuh, 'initialize', 'error'], 'Path: ' + KIBANA_FIELDS_FILE);
|
|
server.log([blueWazuh, 'initialize', 'error'], 'Exception: ' + e);
|
|
};
|
|
|
|
client.update({
|
|
index: '.kibana',
|
|
type: 'index-pattern',
|
|
id: index_pattern,
|
|
body: {
|
|
doc: {
|
|
fields: kibana_fields_data.wazuh_alerts
|
|
}
|
|
}
|
|
}, function (error, response) {
|
|
reply({ 'response': response, 'error': error }).code(200);
|
|
})
|
|
|
|
};
|
|
|
|
//Server routes
|
|
|
|
/*
|
|
* GET /api/wazuh-elastic/top/{manager}/{field}/{time?}
|
|
* Returns the agent with most alerts
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/api/wazuh-elastic/top/{manager}/{field}/{time?}',
|
|
handler: getFieldTop
|
|
});
|
|
|
|
/*
|
|
* GET /api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{time?}
|
|
* Returns the agent with most alerts
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{time?}',
|
|
handler: getFieldTop
|
|
});
|
|
|
|
/*
|
|
* GET /api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{fieldFilter}/{fieldValue}/{time?}
|
|
* Returns the agent with most alerts
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/api/wazuh-elastic/top/{manager}/{field}/{fieldFilter}/{fieldValue}/{fieldFilter2}/{fieldValue2}/{time?}',
|
|
handler: getFieldTop
|
|
});
|
|
|
|
/*
|
|
* GET /api/wazuh-elastic/last/{manager}/{field}
|
|
* Return last field value
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/api/wazuh-elastic/last/{manager}/{field}',
|
|
handler: getLastField
|
|
});
|
|
/*
|
|
|
|
/*
|
|
* GET /api/wazuh-elastic/last/{manager}/{field}/{fieldFilter}/{fieldValue}
|
|
* Return last field value
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'GET',
|
|
path: '/api/wazuh-elastic/last/{manager}/{field}/{fieldFilter}/{fieldValue}',
|
|
handler: getLastField
|
|
});
|
|
/*
|
|
* PUT /api/wazuh-elastic/wazuh-pattern
|
|
* Set wazuh index pattern
|
|
*
|
|
**/
|
|
server.route({
|
|
method: 'PUT',
|
|
path: '/api/wazuh-elastic/wazuh-pattern',
|
|
handler: putWazuhPattern
|
|
});
|
|
}; |