wazuh-kibana-app/server/monitoring.js

373 lines
15 KiB
JavaScript
Raw Normal View History

2018-04-12 13:49:29 +00:00
const cron = require('node-cron');
const needle = require('needle');
const getPath = require('../util/get-path');
const colors = require('ansicolors');
const blueWazuh = colors.blue('wazuh');
const { log } = require('./logger');
const ElasticWrapper = require('./lib/elastic-wrapper');
2018-04-12 13:49:29 +00:00
const index_pattern = "wazuh-monitoring-3.x-*";
const index_prefix = "wazuh-monitoring-3.x-";
module.exports = (server, options) => {
2017-12-11 10:45:32 +00:00
// Elastic JS Client
const wzWrapper = new ElasticWrapper(server);
2017-12-11 10:45:32 +00:00
// Initialize
let agentsArray = [];
2018-04-12 13:49:29 +00:00
2017-12-11 10:45:32 +00:00
let fDate = new Date().toISOString().replace(/T/, '-').replace(/\..+/, '').replace(/-/g, '.').replace(/:/g, '').slice(0, -7);
let todayIndex = index_prefix + fDate;
let packageJSON = {};
// Read Wazuh App package file
try {
packageJSON = require('../package.json');
2018-03-12 11:57:14 +00:00
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring]', error.message || error);
2018-03-12 11:57:14 +00:00
server.log([blueWazuh, 'monitoring', 'error'], 'Could not read the Wazuh package file due to ' + error.message || error);
2017-12-11 10:45:32 +00:00
}
// Check status and get agent status array
2018-03-19 11:21:44 +00:00
const checkStatus = async (apiEntry, maxSize, offset) => {
try {
if (!maxSize) {
throw new Error('You must provide a max size')
}
const payload = {
offset: offset ? offset: 0,
limit : (250 < maxSize) ? 250 : maxSize
};
const options = {
headers: {
'wazuh-app-version': packageJSON.version
},
username: apiEntry.user,
password: apiEntry.password,
rejectUnauthorized: !apiEntry.insecure
};
2018-03-19 12:18:56 +00:00
const response = await needle('get', `${getPath(apiEntry)}/agents`, payload, options);
2017-12-11 10:45:32 +00:00
2018-03-19 11:21:44 +00:00
if (!response.error && response.body.data.items) {
2017-12-11 10:45:32 +00:00
agentsArray = agentsArray.concat(response.body.data.items);
if ((payload.limit + payload.offset) < maxSize) {
2018-03-19 11:21:44 +00:00
return checkStatus(apiEntry, response.body.data.totalItems, payload.limit + payload.offset);
2017-12-11 10:45:32 +00:00
} else {
2018-03-19 11:21:44 +00:00
await saveStatus();
2017-12-11 10:45:32 +00:00
}
} else {
2018-03-19 11:21:44 +00:00
throw new Error('Can not access Wazuh API')
2017-12-11 10:45:32 +00:00
}
2018-03-19 11:21:44 +00:00
return;
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][checkStatus]', error.message || error);
2018-04-11 14:41:14 +00:00
server.log([blueWazuh, 'monitoring', 'error'], error.message || error);
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
// Check API status twice and get agents total items
2018-03-19 11:21:44 +00:00
const checkAndSaveStatus = async apiEntry => {
try{
const payload = {
'offset': 0,
'limit': 1
};
const options = {
headers: {
'wazuh-app-version': packageJSON.version
},
username: apiEntry.user,
password: apiEntry.password,
rejectUnauthorized: !apiEntry.insecure
};
const response = await needle('get', `${getPath(apiEntry)}/agents`, payload, options)
2017-12-11 10:45:32 +00:00
if (!response.error && response.body.data && response.body.data.totalItems) {
checkStatus(apiEntry, response.body.data.totalItems);
} else {
2018-04-12 13:49:29 +00:00
log('[monitoring][checkAndSaveStatus]', 'Wazuh API credentials not found or are not correct. Open the app in your browser and configure it to start monitoring agents.');
2017-12-11 10:45:32 +00:00
server.log([blueWazuh, 'monitoring', 'error'], 'Wazuh API credentials not found or are not correct. Open the app in your browser and configure it to start monitoring agents.');
}
2018-03-19 11:21:44 +00:00
return;
} catch(error){
2018-04-12 13:49:29 +00:00
log('[monitoring][checkAndSaveStatus]',error.message || error);
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'error'], error.message || error);
}
2017-12-11 10:45:32 +00:00
};
// Load Wazuh API credentials from Elasticsearch document
2018-03-19 11:21:44 +00:00
const loadCredentials = async apiEntries => {
try {
if (typeof apiEntries === 'undefined' || !('hits' in apiEntries)) return;
const filteredApis = apiEntries.hits.filter((element, index, self) =>
index === self.findIndex((t) => (
t._source.api_user === element._source.api_user &&
t._source.api_password === element._source.api_password &&
t._source.url === element._source.url &&
t._source.api_port === element._source.api_port
))
);
for(let element of filteredApis) {
let apiEntry = {
'user': element._source.api_user,
'password': Buffer.from(element._source.api_password, 'base64').toString("ascii"),
'url': element._source.url,
'port': element._source.api_port,
'insecure': element._source.insecure
};
if (apiEntry.error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][loadCredentials]', apiEntry.error || apiEntry);
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'error'], `Error getting wazuh-api data: ${apiEntry.error}`);
break;
}
await checkAndSaveStatus(apiEntry);
2017-12-11 10:45:32 +00:00
}
2018-03-19 11:21:44 +00:00
} catch(error){
2018-04-12 13:49:29 +00:00
log('[monitoring][loadCredentials]',error.message || error);
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'error'], error.message || error);
2017-12-11 10:45:32 +00:00
}
};
// Get API configuration from elastic and callback to loadCredentials
const getConfig = async () => {
2018-03-19 11:21:44 +00:00
try {
const data = await wzWrapper.getWazuhAPIEntries();
2018-03-19 11:21:44 +00:00
if (data.hits.total > 0) {
return data.hits;
2017-12-11 10:45:32 +00:00
}
2018-03-19 11:21:44 +00:00
2018-04-12 13:49:29 +00:00
log('[monitoring][getConfig]','no credentials');
return {
error : 'no credentials',
error_code: 1
};
2018-03-19 11:21:44 +00:00
} catch (error){
2018-04-12 13:49:29 +00:00
log('[monitoring][getConfig]',error.message || error);
return {
error : 'no elasticsearch',
error_code: 2
};
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
// fetchAgents on demand
const fetchAgents = async () => {
try {
const data = await getConfig();
return loadCredentials(data);
} catch(error){
return Promise.reject(error);
}
};
2017-12-11 10:45:32 +00:00
// Configure Kibana patterns.
2018-03-19 11:21:44 +00:00
const configureKibana = async () => {
try {
2018-04-12 13:49:29 +00:00
log('[monitoring][configureKibana]', `Creating index pattern: ${index_pattern}`, 'info');
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'info'], `Creating index pattern: ${index_pattern}`);
await wzWrapper.createMonitoringIndexPattern(index_pattern);
2018-04-12 13:49:29 +00:00
log('[monitoring][configureKibana]', `Created index pattern: ${index_pattern}`, 'info');
2018-03-12 11:57:14 +00:00
server.log([blueWazuh, 'monitoring', 'info'], `Created index pattern: ${index_pattern}`);
2018-03-19 11:21:44 +00:00
return;
} catch(error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][configureKibana]',error.message || error);
2017-12-11 10:45:32 +00:00
server.log([blueWazuh, 'monitoring', 'error'], 'Error creating index-pattern due to ' + error);
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
// Creating wazuh-monitoring index
2018-03-19 11:21:44 +00:00
const createIndex = async todayIndex => {
try {
await wzWrapper.createIndexByName(todayIndex);
2018-04-12 13:49:29 +00:00
log('[monitoring][createIndex]', 'Successfully created today index.', 'info');
2017-12-11 10:45:32 +00:00
server.log([blueWazuh, 'monitoring', 'info'], 'Successfully created today index.');
2018-03-19 11:21:44 +00:00
await insertDocument(todayIndex);
return;
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][createIndex]', error.message || error);
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'error'], `Could not create ${todayIndex} index on elasticsearch due to ` + error.message || error);
}
2017-12-11 10:45:32 +00:00
};
// Inserting one document per agent into Elastic. Bulk.
2018-03-19 11:21:44 +00:00
const insertDocument = async todayIndex => {
try {
let body = '';
if (agentsArray.length > 0) {
let managerName = agentsArray[0].name;
for(let element of agentsArray) {
body += '{ "index": { "_index": "' + todayIndex + '", "_type": "wazuh-agent" } }\n';
let date = new Date(Date.now()).toISOString();
element["@timestamp"] = date;
element["host"] = managerName;
body += JSON.stringify(element) + "\n";
}
if (body === '') return;
const response = await wzWrapper.pushBulkAnyIndex(todayIndex,body);
2017-12-11 10:45:32 +00:00
2018-03-19 11:21:44 +00:00
agentsArray.length = 0;
}
return;
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][insertDocument]', error.message || error);
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'error'], 'Error inserting agent data into elasticsearch. Bulk request failed due to ' + error.message || error);
2017-12-11 10:45:32 +00:00
}
};
// Save agent status into elasticsearch, create index and/or insert document
2018-03-19 11:21:44 +00:00
const saveStatus = async () => {
try {
fDate = new Date().toISOString().replace(/T/, '-').replace(/\..+/, '').replace(/-/g, '.').replace(/:/g, '').slice(0, -7);
todayIndex = index_prefix + fDate;
const result = await wzWrapper.checkIfIndexExists(todayIndex);
2018-03-19 11:21:44 +00:00
result ? await insertDocument(todayIndex) : await createIndex(todayIndex);
return;
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][saveStatus]', `Could not check if the index ${todayIndex} exists due to ${error.message || error}`);
2017-12-11 10:45:32 +00:00
server.log([blueWazuh, 'monitoring', 'error'], `Could not check if the index ${todayIndex} exists due to ` + error);
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
2018-03-19 11:21:44 +00:00
const createWazuhMonitoring = async () => {
try{
try{
await wzWrapper.deleteMonitoring();
2018-04-12 13:49:29 +00:00
log('[monitoring][createWazuhMonitoring]', 'Successfully deleted old wazuh-monitoring pattern.', 'info');
server.log([blueWazuh, 'monitoring', 'info'], "Successfully deleted old wazuh-monitoring pattern.");
} catch (error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][createWazuhMonitoring]', 'No need to delete old wazuh-monitoring pattern.', 'info');
server.log([blueWazuh, 'monitoring', 'info'], "No need to delete old wazuh-monitoring pattern.");
}
2018-03-19 11:21:44 +00:00
await configureKibana();
return;
}catch(error){
return Promise.reject(error);
}
}
const checkTemplate = async () => {
try {
2018-04-12 13:49:29 +00:00
log('[monitoring][checkTemplate]', 'Updating wazuh-monitoring template...', 'info');
2018-03-19 14:11:36 +00:00
server.log([blueWazuh, 'monitoring', 'info'], "Updating wazuh-monitoring template...");
2018-03-19 11:21:44 +00:00
const monitoringTemplate = require('./integration-files/monitoring-template');
const data = await wzWrapper.putMonitoringTemplate(monitoringTemplate);
2018-03-19 11:21:44 +00:00
return;
} catch(error){
2018-04-12 13:49:29 +00:00
log('[monitoring][checkTemplate]', 'Something went wrong updating wazuh-monitoring template...' + error.message || error);
2018-03-19 14:11:36 +00:00
server.log([blueWazuh, 'monitoring', 'info'], "Something went wrong updating wazuh-monitoring template..." + error.message || error);
2018-03-19 11:21:44 +00:00
return Promise.reject(error);
}
}
// Main. First execution when installing / loading App.
const init = async () => {
try {
2018-04-12 13:49:29 +00:00
log('[monitoring][init]', 'Creating/Updating wazuh-agent template...', 'info');
2018-03-19 11:21:44 +00:00
await checkTemplate();
2018-04-12 13:49:29 +00:00
log('[monitoring][init]', 'Creating today index...', 'info');
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'info'], 'Creating today index...');
await saveStatus();
const patternId = 'index-pattern:' + index_pattern;
// Checks if wazuh-monitoring index pattern is already created, if it fails create it
try{
2018-04-12 13:49:29 +00:00
log('[monitoring][init]', 'Checking if wazuh-monitoring pattern exists...', 'info');
server.log([blueWazuh, 'monitoring', 'info'], 'Checking if wazuh-monitoring pattern exists...');
await wzWrapper.getIndexPatternUsingGet(patternId);
} catch (error) {
log('[monitoring][init]', 'Didn\'t find wazuh-monitoring pattern for Kibana v6.x. Proceeding to create it...','info');
server.log([blueWazuh, 'monitoring', 'info'], "Didn't find wazuh-monitoring pattern for Kibana v6.x. Proceeding to create it...");
return createWazuhMonitoring();
}
2018-04-12 13:49:29 +00:00
log('[monitoring][init]', 'Skipping wazuh-monitoring pattern creation. Already exists.', 'info');
server.log([blueWazuh, 'monitoring', 'info'], 'Skipping wazuh-monitoring creation. Already exists.');
2018-03-19 11:21:44 +00:00
return;
} catch (error) {
server.log([blueWazuh, 'monitoring', 'error'], error.message || error);
2018-04-12 13:49:29 +00:00
log('[monitoring][init]', error.message || error);
return;
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
2017-06-01 15:08:10 +00:00
// Check Elasticsearch Server status and Kibana index presence
2018-03-19 11:21:44 +00:00
const checkElasticsearchServer = async () => {
try {
const data = await wzWrapper.checkIfIndexExists(wzWrapper.WZ_KIBANA_INDEX);
2018-03-19 11:21:44 +00:00
if (data) {
const pluginsData = await server.plugins.elasticsearch.waitUntilReady();
return pluginsData;
}
return Promise.reject(data);
} catch(error){
2018-04-12 13:49:29 +00:00
log('[monitoring][checkElasticsearchServer]',error.message || error);
2018-03-19 11:21:44 +00:00
return Promise.reject(error);
}
}
2017-12-11 10:45:32 +00:00
// Wait until Kibana server is ready
2018-03-19 11:21:44 +00:00
const checkKibanaStatus = async () => {
try {
2018-04-12 13:49:29 +00:00
log('[monitoring][checkKibanaStatus]','Waiting for Kibana and Elasticsearch servers to be ready...','info');
2018-03-19 11:21:44 +00:00
server.log([blueWazuh, 'monitoring', 'info'], 'Waiting for Kibana and Elasticsearch servers to be ready...');
await checkElasticsearchServer();
await init();
return;
} catch(error) {
2018-04-12 13:49:29 +00:00
log('[monitoring][checkKibanaStatus]',error.message || error);
server.log([blueWazuh, 'monitoring', 'info'], 'Waiting for Kibana and Elasticsearch servers to be ready...','info');
setTimeout(() => checkKibanaStatus(), 3000);
2018-03-19 11:21:44 +00:00
}
2017-12-11 10:45:32 +00:00
};
2017-06-01 15:08:10 +00:00
2017-12-11 10:45:32 +00:00
// Check Kibana index and if it is prepared, start the initialization of Wazuh App.
checkKibanaStatus();
2017-06-01 15:08:10 +00:00
2018-04-12 13:49:29 +00:00
const cronTask = async () => {
try {
agentsArray = [];
const data = await getConfig();
await loadCredentials(data);
return;
} catch (error) {
log('[monitoring][cronTask]',error.message || error);
server.log([blueWazuh, 'monitoring [cronTask]', 'error'], error.message || error)
}
}
cronTask()
2017-12-11 10:45:32 +00:00
// Cron tab for getting agent status.
2018-04-12 13:49:29 +00:00
cron.schedule('0 */10 * * * *', cronTask, true);
2017-06-01 15:08:10 +00:00
2017-12-11 10:45:32 +00:00
module.exports = fetchAgents;
};