wazuh-kibana-app/server/reporting/raw-parser.js
2019-01-14 17:36:47 +01:00

257 lines
8.1 KiB
JavaScript

/*
* Wazuh app - Elasticsearch data table raw response parser
* Copyright (C) 2015-2019 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.
*/
/**
* Aggregation which starts in level 2
* @param {*} data_set The raw response.
*/
const parse_start_2 = data_set => {
const tree = {};
for (const main_bucket of data_set.aggregations['2'].buckets) {
if (!tree[main_bucket.key]) tree[main_bucket.key] = {};
if (main_bucket['3'] && main_bucket['3'].buckets) {
for (const sub_bucket of main_bucket['3'].buckets) {
if (!tree[main_bucket.key][sub_bucket.key])
tree[main_bucket.key][sub_bucket.key] = {};
if (sub_bucket['4'] && sub_bucket['4'].buckets) {
for (const sub_sub_bucket of sub_bucket['4'].buckets) {
if (!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key])
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
if (sub_sub_bucket['5'] && sub_sub_bucket['5'].buckets) {
for (const sub_sub_sub_bucket of sub_sub_bucket['5'].buckets) {
if (
!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
sub_sub_sub_bucket.key
]
) {
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
sub_sub_sub_bucket.key
] = {};
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
sub_sub_sub_bucket.key
][sub_sub_sub_bucket.doc_count] = false;
}
}
} else {
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
sub_sub_bucket.doc_count
] = false;
}
}
}
if (sub_bucket['5'] && sub_bucket['5'].buckets) {
for (const sub_sub_bucket of sub_bucket['5'].buckets) {
if (!tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key]) {
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key] = {};
tree[main_bucket.key][sub_bucket.key][sub_sub_bucket.key][
sub_sub_bucket.doc_count
] = false;
}
}
}
if (
!(sub_bucket['4'] && sub_bucket['4'].buckets) &&
!(sub_bucket['5'] && sub_bucket['5'].buckets)
) {
tree[main_bucket.key][sub_bucket.key] = {};
tree[main_bucket.key][sub_bucket.key][sub_bucket.doc_count] = false;
}
}
} else {
tree[main_bucket.key] = {};
tree[main_bucket.key][main_bucket.doc_count] = false;
}
}
return tree;
};
/**
* Aggregation which starts in level 3
* @param {*} data_set The raw response.
*/
const parse_start_3 = data_set => {
const tree = {};
for (const sub_bucket of data_set.aggregations['3'].buckets) {
if (!tree[sub_bucket.key]) tree[sub_bucket.key] = {};
if (sub_bucket['4'] && sub_bucket['4'].buckets) {
for (const sub_sub_bucket of sub_bucket['4'].buckets) {
if (!tree[sub_bucket.key][sub_sub_bucket.key])
tree[sub_bucket.key][sub_sub_bucket.key] = {};
if (sub_sub_bucket['5'] && sub_sub_bucket['5'].buckets) {
for (const sub_sub_sub_bucket of sub_sub_bucket['5'].buckets) {
if (
!tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key]
) {
tree[sub_bucket.key][sub_sub_bucket.key][
sub_sub_sub_bucket.key
] = {};
tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key][
sub_sub_sub_bucket.doc_count
] = false;
}
}
} else {
tree[sub_bucket.key][sub_sub_bucket.key] = {};
tree[sub_bucket.key][sub_sub_bucket.key][
sub_sub_bucket.doc_count
] = false;
}
}
}
if (sub_bucket['5'] && sub_bucket['5'].buckets) {
for (const sub_sub_bucket of sub_bucket['5'].buckets) {
if (!tree[sub_bucket.key][sub_sub_bucket.key]) {
tree[sub_bucket.key][sub_sub_bucket.key] = {};
tree[sub_bucket.key][sub_sub_bucket.key][
sub_sub_bucket.doc_count
] = false;
}
}
}
if (
!(sub_bucket['4'] && sub_bucket['4'].buckets) &&
!(sub_bucket['5'] && sub_bucket['5'].buckets)
) {
tree[sub_bucket.key] = {};
tree[sub_bucket.key][sub_bucket.doc_count] = false;
}
}
return tree;
};
/**
* Aggregation which starts in level 3 and continues with level 2 buckets
* @param {*} data_set The raw response.
*/
const parse_start_3_mix_2 = data_set => {
const tree = {};
for (const sub_bucket of data_set.aggregations['3'].buckets) {
if (!tree[sub_bucket.key]) tree[sub_bucket.key] = {};
if (sub_bucket['2'] && sub_bucket['2'].buckets) {
for (const sub_sub_bucket of sub_bucket['2'].buckets) {
if (!tree[sub_bucket.key][sub_sub_bucket.key])
tree[sub_bucket.key][sub_sub_bucket.key] = {};
if (sub_sub_bucket['6'] && sub_sub_bucket['6'].buckets) {
for (const sub_sub_sub_bucket of sub_sub_bucket['6'].buckets) {
if (
!tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key]
) {
tree[sub_bucket.key][sub_sub_bucket.key][
sub_sub_sub_bucket.key
] = {};
tree[sub_bucket.key][sub_sub_bucket.key][sub_sub_sub_bucket.key][
sub_sub_sub_bucket.doc_count
] = false;
}
}
} else {
tree[sub_bucket.key][sub_sub_bucket.key] = {};
tree[sub_bucket.key][sub_sub_bucket.key][
sub_sub_bucket.doc_count
] = false;
}
}
}
}
return tree;
};
/**
* Generates a hierarchical tree from the raw response.
* @param {*} data_set The raw response. Must have aggregations and buckets for level 0.
*/
const generate_tree = data_set => {
// If we have no aggregations just return empty object
if (!data_set || !data_set.aggregations) {
return {};
}
// If the aggregation from Elasticsearch starts using level 2
if (data_set.aggregations['2'] && data_set.aggregations['2'].buckets) {
return parse_start_2(data_set);
}
// If the aggregation from Elasticsearch starts using level 3 and continues using level 2
if (
data_set.aggregations['3'] &&
data_set.aggregations['3'].buckets &&
data_set.aggregations['3'].buckets[0] &&
data_set.aggregations['3'].buckets[0]['2'] &&
data_set.aggregations['3'].buckets[0]['2'].buckets
) {
return parse_start_3_mix_2(data_set);
}
// If the aggregation from Elasticsearch starts using level 3
if (data_set.aggregations['3'] && data_set.aggregations['3'].buckets) {
return parse_start_3(data_set);
}
// If none of the above conditions are true, return empty object
return {};
};
/**
* Generates a matrix which includes each parsed row
* @param {*} item Hierarchical tree generated from a raw response
*/
const generate_rows = item => {
const iter = (r, p) => {
const keys = Object.keys(r);
if (keys.length) {
return keys.forEach(x => iter(r[x], p.concat(x)));
}
result.push(p);
};
const result = [];
iter(item, []);
return result;
};
/**
* Public function to enter the module.
* Always returns an array (could be empty)
* @param {*} data_set The raw response.
*/
export default (data_set, cols) => {
try {
const tree = generate_tree(data_set);
const min_size = cols.length;
// Minimum validation for the generated tree
if (!tree || !Object.keys(tree) || !Object.keys(tree).length) return [];
// All rows must have same length
const rows = generate_rows(tree).filter(item => item.length === min_size);
return rows;
} catch (error) {
return [];
}
};