wazuh-kibana-app/server/api/wazuh-elastic.js
2018-01-18 18:01:34 +01:00

365 lines
11 KiB
JavaScript

const importAppObjects = require('../initialize');
module.exports = (server, options) => {
// Elastic JS Client
const elasticRequest = server.plugins.elasticsearch.getCluster('data');
//Handlers
const fetchElastic = (req, payload) => {
return elasticRequest.callWithRequest(req, 'search', {
index: 'wazuh-alerts-3.x-*',
type: 'wazuh',
body: payload
});
};
const getConfig = (id, callback) => {
elasticRequest.callWithInternalUser('get', {
index: '.wazuh',
type: 'wazuh-configuration',
id: id
})
.then((data) => {
callback({
'user': data._source.api_user,
'password': Buffer.from(data._source.api_password, 'base64').toString("ascii"),
'url': data._source.url,
'port': data._source.api_port,
'insecure': data._source.insecure,
'cluster_info': data._source.cluster_info,
'extensions': data._source.extensions
});
})
.catch((error) => {
callback({
'error': 'no elasticsearch',
'error_code': 2
});
});
};
// Updating Wazuh app visualizations and dashboards
const updateAppObjects = (req, reply) => {
elasticRequest.callWithInternalUser('deleteByQuery', {
index: '.kibana',
body: {
'query': {
'bool': {
'must': {
'match': {
"visualization.title": 'Wazuh App*'
}
},
'must_not': {
"match": {
"visualization.title": 'Wazuh App Overview General Agents status'
}
}
}
}
}
})
.then((resp) => {
// Update the pattern in the configuration
importAppObjects(req.params.pattern);
reply({
'statusCode': 200,
'data': 'Index pattern updated'
});
})
.catch((err) => {
reply({
'statusCode': 500,
'error': 9,
'message': 'Could not delete visualizations'
}).code(500);
});
};
const getTemplate = (req, reply) => {
elasticRequest.callWithInternalUser('cat.templates', {})
.then((data) => {
if (req.params.pattern == "wazuh-alerts-3.x-*" && data.includes("wazuh-alerts-3.*")) {
reply({
'statusCode': 200,
'status': true,
'data': `Template found for ${req.params.pattern}`
});
} else {
let lastChar = req.params.pattern[req.params.pattern.length -1];
let array = data.match(/[^\s]+/g);
let found = false;
let pattern = req.params.pattern;
if (lastChar === '*') { // Remove last character if it is a '*'
pattern = pattern.slice(0, -1);
}
for (let i = 1; i < array.length; i++) {
if (array[i].includes(pattern) && array[i-1] == `wazuh`) {
found = true;
reply({
'statusCode': 200,
'status': true,
'data': `Template found for ${req.params.pattern}`
});
}
}
if (!found) {
reply({
'statusCode': 200,
'status': false,
'data': `No template found for ${req.params.pattern}`
});
}
}
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 10000,
'message': 'Could not retrieve templates from Elasticsearch'
}).code(500);
});
};
const checkPattern = (req, reply) => {
elasticRequest.callWithInternalUser('search', {
index: '.kibana',
body: {
'query': {
'bool': {
'must': {
'match': {
"type": 'index-pattern'
}
}
}
}
}
})
.then((response) => {
// Looking for the pattern
for (let i = 0, len = response.hits.hits.length; i < len; i++) {
if (response.hits.hits[i]._source['index-pattern'].title == req.params.pattern) {
return reply({
'statusCode': 200,
'status': true,
'data': 'Index pattern found'
});
}
}
return reply({
'statusCode': 200,
'status': false,
'data': 'Index pattern not found'
});
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 10000,
'message': 'Something went wrong retrieving index-patterns from Elasticsearch'
}).code(500);
});
};
const getFieldTop = (req, reply) => {
// Top field payload
var payload = {
"size": 1,
"query": {
"bool": {
"must": [],
"filter": {
"range": {
"@timestamp": {}
}
}
}
},
"aggs": {
"2": {
"terms": {
"field": "",
"size": 1,
"order": {
"_count": "desc"
}
}
}
}
};
// Set up time interval, default to Last 24h
const timeGTE = 'now-1d';
const timeLT = 'now';
payload.query.bool.filter.range['@timestamp']['gte'] = timeGTE;
payload.query.bool.filter.range['@timestamp']['lt'] = timeLT;
if (req.params.mode === 'cluster') {
// Set up match for default cluster name
payload.query.bool.must.push({
"match": {
"cluster.name": req.params.cluster
}
});
} else {
// Set up match for default cluster name
payload.query.bool.must.push({
"match": {
"manager.name": req.params.cluster
}
});
}
payload.aggs['2'].terms.field = req.params.field;
fetchElastic(req, payload)
.then((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
});
}
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 9,
'message': 'Could not get data from elasticsearch'
}).code(500);
});
};
const getSetupInfo = (req, reply) => {
elasticRequest
.callWithInternalUser('search', {
index: '.wazuh-version',
type: 'wazuh-version'
})
.then((data) => {
if (data.hits.total === 0) {
reply({
'statusCode': 200,
'data': ''
});
} else {
reply({
'statusCode': 200,
'data': data.hits.hits[0]._source
});
}
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 9,
'message': 'Could not get data from elasticsearch'
}).code(500);
});
};
const getCurrentlyAppliedPattern = (req, reply) => {
// We search for the currently applied pattern in the visualizations
elasticRequest .callWithInternalUser('search', {
index: '.kibana',
type: 'doc',
q: `visualization.title:"Wazuh App Overview General Metric alerts"`
})
.then((data) => {
reply({
'statusCode': 200,
'data': JSON.parse(data.hits.hits[0]._source.visualization.kibanaSavedObjectMeta.searchSourceJSON).index
});
})
.catch((error) => {
reply({
'statusCode': 500,
'error': 10000,
'message': error
}).code(500);
});
};
module.exports = getConfig;
//Server routes
/*
* GET /api/wazuh-elastic/current-pattern
* Returns the currently applied pattern
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/current-pattern',
handler: getCurrentlyAppliedPattern
});
/*
* GET /api/wazuh-elastic/template/{pattern}
* Returns whether a correct template is being applied for the index-pattern
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/template/{pattern}',
handler: getTemplate
});
/*
* GET /api/wazuh-elastic/pattern/{pattern}
* Returns whether the pattern exists or not
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/pattern/{pattern}',
handler: checkPattern
});
/*
* GET /api/wazuh-elastic/top/{cluster}/{field}/{time?}
* Returns the agent with most alerts
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/top/{mode}/{cluster}/{field}',
handler: getFieldTop
});
/*
* GET /api/wazuh-elastic/setup
* Return Wazuh Appsetup info
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/setup',
handler: getSetupInfo
});
/*
* POST /api/wazuh-elastic/updatePattern
* Update the index pattern in the app visualizations
*
**/
server.route({
method: 'GET',
path: '/api/wazuh-elastic/updatePattern/{pattern}',
handler: updateAppObjects
});
};