Merge branch 'ent-9857-complex-alert-processing' into 'develop'

Ent-9857-complex-alert-processing

Closes pandora_enterprise#9857

See merge request artica/pandorafms!6347
This commit is contained in:
Rafael Ameijeiras 2023-09-21 15:41:24 +00:00
commit d136b7a9e3
5 changed files with 279 additions and 2 deletions

View File

@ -23,6 +23,12 @@ UPDATE tagente_modulo SET `tcp_send` = '2c' WHERE `tcp_send` = '2';
UPDATE tpolicy_modules SET `tcp_send` = '2c' WHERE `tcp_send` = '2';
UPDATE tnetwork_component SET `tcp_send` = '2c' WHERE `tcp_send` = '2';
ALTER TABLE talert_templates
ADD COLUMN `time_window` ENUM ('thirty_days','this_month','seven_days','this_week','one_day','today'),
ADD COLUMN `math_function` ENUM ('avg', 'min', 'max', 'sum'),
ADD COLUMN `condition` ENUM ('lower', 'greater', 'equal'),
MODIFY COLUMN `type` ENUM ('regex', 'max_min', 'max', 'min', 'equal', 'not_equal', 'warning', 'critical', 'onchange', 'unknown', 'always', 'not_normal', 'complex');
ALTER TABLE `tsesion_filter_log_viewer`
CHANGE COLUMN `date_range` `custom_date` INT NULL DEFAULT NULL ,
CHANGE COLUMN `start_date_defined` `date` VARCHAR(45) NULL DEFAULT NULL ,
@ -66,4 +72,5 @@ ALTER TABLE `treport_content` ADD COLUMN `cat_security_hardening` INT NOT NULL
ALTER TABLE `treport_content` ADD COLUMN `ignore_skipped` INT NOT NULL DEFAULT 0;
ALTER TABLE `treport_content` ADD COLUMN `status_of_check` TINYTEXT;
COMMIT;

View File

@ -374,6 +374,9 @@ function update_template($step)
$max = (float) get_parameter('max');
$min = (float) get_parameter('min');
$matches = (bool) get_parameter('matches_value');
$math_function = (string) get_parameter('math_function');
$condition = (string) get_parameter('condition');
$time_window = (string) get_parameter('time_window');
$default_action = (int) get_parameter('default_action');
if (empty($default_action) === true) {
@ -394,6 +397,9 @@ function update_template($step)
'min_value' => $min,
'matches_value' => $matches,
'disable_event' => $disable_event,
'math_function' => $math_function,
'condition' => $condition,
'time_window' => $time_window,
];
$result = alerts_update_alert_template($id, $values);
@ -607,6 +613,9 @@ if ($id && ! $create_template) {
$max = $template['max_value'];
$min = $template['min_value'];
$matches = $template['matches_value'];
$math_function = $template['math_function'];
$condition = $template['condition'];
$time_window = $template['time_window'];
$schedule = json_encode(
$default_events_calendar
@ -856,6 +865,58 @@ if ($step == 2) {
).'</span>'
);
$table->data["math_function"][0] = html_print_label_input_block(
__('Math function'),
html_print_select(
alerts_get_alert_templates_functions(),
'math_function',
$math_function,
'',
__('None'),
0,
true,
false,
false,
'w100p',
(!$is_management_allowed | $disabled)
)
);
$table->data["time_window"][0] = html_print_label_input_block(
__('Time window').ui_print_help_tip(__('Limits to data in the following time window.'), true),
html_print_select(
alerts_get_alert_templates_windows(),
'time_window',
$time_window,
'',
__('None'),
0,
true,
false,
false,
'w100p',
(!$is_management_allowed | $disabled)
)
);
$table->data["condition"][0] = html_print_label_input_block(
__('Alert condition'),
html_print_select(
alerts_get_alert_templates_conditions(),
'condition',
$condition,
'',
__('None'),
0,
true,
false,
false,
'w100p',
(!$is_management_allowed | $disabled)
)
);
$table->data['value'][1] = html_print_label_input_block(
__('Value'),
html_print_input_text(
@ -1088,6 +1149,12 @@ if ($step == 2) {
$table->rowstyle['min'] = '';
break;
case 'complex':
$table->rowstyle['math_function'] = '';
$table->rowstyle['condition'] = '';
$table->rowstyle['time_window'] = '';
break;
case 'onchange':
$show_matches = true;
break;
@ -1299,6 +1366,7 @@ var onchange_not = <?php echo '"'.__('The alert would fire when the module value
var unknown = <?php echo "'".__('The alert would fire when the module is in unknown status')."'"; ?>;
var error_message_min_max_zero = <?php echo "'".__('The alert template cannot have the same value for min and max thresholds.')."'"; ?>;
var not_normal = <?php echo "'".__('The alert would fire when the module is in not normal status')."'"; ?>;
var complex = <?php echo "'".__('Alert would fire when the <span id="math_function"></span> within <span id="time_window"></span> <span id="condition"></span> <span id="value"></span>')."'"; ?>;
function check_fields_step2() {
var correct = true;
@ -1361,6 +1429,68 @@ function render_example () {
else {
$("span#value").empty ().append (vvalue);
}
/* Set math function */
var vfunction = $("select#math_function").val();
var functionMessage = "";
if (vfunction == "0") {
functionMessage = "<em><?php echo __('[function]'); ?></em>";
} else {
if (vfunction == "avg"){
$("span#value").empty ();
}
functionMessage = vfunction;
}
$("span#math_function").empty ().append (functionMessage);
/* Set complex value */
if($("select#type").val() == "complex"){
var valueMessage = "";
if(vfunction == "avg"){
valueMessage = "";
}else if (vvalue == "") {
valueMessage = "<em><?php echo __('[value]'); ?></em>" ;
} else {
valueMessage = vvalue;
}
$("span#value").empty ().append (valueMessage);
}
/* Set condition */
var vCondition = $("select#condition").val();
var conditionMessage = "<em><?php echo __('[condition]'); ?></em>" ;
switch (vCondition){
case "greater":
conditionMessage = (vfunction == "avg") ? "increases" : "is more than";
break
case "lower":
conditionMessage = (vfunction == "avg") ? "decreases" : "is less than";
break
case "equal":
conditionMessage = (vfunction == "avg") ? "remains the same" : "is equal to";
break
}
$("span#condition").empty ().append (conditionMessage);
var vWindow = $("select#time_window").val();
/* Set time window */
var timeWindowMessages = {
"thirty_days": "the last 30 days",
"month": "the last month",
"seven_days": "the last 7 days",
"week": "the last week",
"one_day": "the last 24 hours",
"today": "today"
};
var windowMessage = timeWindowMessages[vWindow] || "<em><?php echo __(' the last [window]'); ?></em>";
$("span#time_window").empty().append(windowMessage);
}
// Fix for metaconsole toggle
@ -1388,6 +1518,18 @@ if ($step == 2) {
$("input#text-value").keyup (render_example);
$("input#text-max").keyup (render_example);
$("input#text-min").keyup (render_example);
$("#condition").change (render_example);
$("#time_window").change (render_example);
$("#math_function").change (function () {
if (["0", 'avg'].includes(this.value)) {
$("#template-value").hide();
} else {
$("#template-value").show ();
}
render_example ();
})
$("#type").change (function () {
switch (this.value) {
@ -1395,6 +1537,7 @@ if ($step == 2) {
case "not_equal":
$("img#regex_good, img#regex_bad, span#matches_value").hide ();
$("#template-max, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-value, #template-example").show ();
/* Show example */
@ -1405,6 +1548,7 @@ if ($step == 2) {
break;
case "regex":
$("#template-max, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-value, #template-example, span#matches_value").show ();
check_regex ();
@ -1416,6 +1560,7 @@ if ($step == 2) {
break;
case "max_min":
$("#template-value").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-max, #template-min, #template-example, span#matches_value").show ();
/* Show example */
@ -1424,9 +1569,25 @@ if ($step == 2) {
else
$("span#example").empty ().append (between_not);
break;
case "complex":
$("pan#matches_value, #template-example, #template-value, #template-max, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").show ();
$("#template-example").show ();
if (["0", 'avg'].includes($("#math_function").val())) {
$("#template-value").hide();
}else {
$("#template-value").show();
}
/* Show example */
$("span#example").empty ().append (complex);
break;
case "max":
$("#template-value, #template-min, span#matches_value").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-max, #template-example").show ();
/* Show example */
@ -1434,6 +1595,7 @@ if ($step == 2) {
break;
case "min":
$("#template-value, #template-max, span#matches_value").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-min, #template-example").show ();
/* Show example */
@ -1441,6 +1603,7 @@ if ($step == 2) {
break;
case "warning":
$("#template-value, #template-max, span#matches_value, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-example").show ();
/* Show example */
@ -1448,6 +1611,7 @@ if ($step == 2) {
break;
case "critical":
$("#template-value, #template-max, span#matches_value, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-example").show ();
/* Show example */
@ -1455,6 +1619,7 @@ if ($step == 2) {
break;
case "not_normal":
$("#template-value, #template-max, span#matches_value, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-example").show ();
/* Show example */
@ -1462,6 +1627,7 @@ if ($step == 2) {
break;
case "onchange":
$("#template-value, #template-max, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-example, span#matches_value").show ();
/* Show example */
@ -1472,6 +1638,7 @@ if ($step == 2) {
break;
case "unknown":
$("#template-value, #template-max, span#matches_value, #template-min").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
$("#template-example").show ();
if ($("#text-min_alerts").val() > 0 ) {
@ -1483,6 +1650,7 @@ if ($step == 2) {
break;
default:
$("#template-value, #template-max, #template-min, #template-example, span#matches_value").hide ();
$("#template-math_function, #template-condition, #template-time_window").hide ();
break;
}

View File

@ -688,11 +688,67 @@ function alerts_get_alert_templates_types()
$types['onchange'] = __('On Change');
$types['always'] = __('Always');
$types['not_normal'] = __('Not normal status');
$types['complex'] = __('Complex alert');
return $types;
}
/**
* Get matemathical functions for complex alert templates.
*
* @return array Mathematical function for complex templates.
*/
function alerts_get_alert_templates_functions()
{
$functions = [];
$functions['avg'] = __('Avg.');
$functions['sum'] = __('Sum.');
$functions['max'] = __('Max.');
$functions['min'] = __('Min.');
return $functions;
}
/**
* Get conditions for complex alert templates.
*
* @return array Conditions for complex templates.
*/
function alerts_get_alert_templates_conditions()
{
$conditions = [];
$conditions['lower'] = __('&lt;');
$conditions['greater'] = __('&gt;');
$conditions['equal'] = __('=');
return $conditions;
}
/**
* Get time windows for complex alert templates.
*
* @return array Windows for complex templates.
*/
function alerts_get_alert_templates_windows()
{
$windows = [];
$windows['thirty_days'] = __('Last 30 days');
$windows['month'] = __('This month');
$windows['seven_days'] = __('Last 7 days');
$windows['week'] = __('This week');
$windows['one_day'] = __('Last 24 hours');
$windows['today'] = __('Today');
return $windows;
}
/**
* Get type name of an alert template.
*

View File

@ -484,11 +484,14 @@ CREATE TABLE IF NOT EXISTS `talert_templates` (
`field18` TEXT,
`field19` TEXT,
`field20` TEXT,
`type` ENUM ('regex', 'max_min', 'max', 'min', 'equal', 'not_equal', 'warning', 'critical', 'onchange', 'unknown', 'always', 'not_normal'),
`type` ENUM ('regex', 'max_min', 'max', 'min', 'equal', 'not_equal', 'warning', 'critical', 'onchange', 'unknown', 'always', 'not_normal', 'complex'),
`value` VARCHAR(255) DEFAULT '',
`matches_value` TINYINT DEFAULT 0,
`max_value` DOUBLE DEFAULT NULL,
`min_value` DOUBLE DEFAULT NULL,
`time_window` ENUM ('thirty_days','this_month','seven_days','this_week','one_day','today'),
`math_function` ENUM ('avg', 'min', 'max', 'sum'),
`condition` ENUM ('lower', 'greater', 'equal'),
`time_threshold` INT NOT NULL DEFAULT 0,
`max_alerts` INT UNSIGNED NOT NULL DEFAULT 1,
`min_alerts` INT UNSIGNED NOT NULL DEFAULT 0,

View File

@ -705,6 +705,49 @@ sub pandora_evaluate_alert ($$$$$$$;$$$$) {
}
}
if($alert-> {'type'} eq "complex") {
my @allowed_functions = ("sum", "min", "max", "avg");
my %condition_map = (
lower => '<',
greater => '>',
equal => '==',
);
my %time_windows_map = (
thirty_days => sub { return time - 30 * 24 * 60 * 60 },
this_month => sub { return timelocal(0, 0, 0, 1, (localtime)[4, 5]) },
seven_days => sub { return time - 7 * 24 * 60 * 60 },
this_week => sub { return time - ((localtime)[6] % 7) * 24 * 60 * 60 },
one_day => sub { return time - 1 * 24 * 60 * 60 },
today => sub { return timelocal(0, 0, 0, (localtime)[3, 4, 5]) },
);
my $function = $alert-> {'math_function'};
my $condition = $condition_map{$alert->{'condition'}};
my $window = $time_windows_map{$alert->{'time_window'}};
my $value = defined $alert->{'value'} && $alert->{'value'} ne "" ? $alert->{'value'} : 0;
if((grep { $_ eq $function } @allowed_functions) == 1 && defined($condition) && defined($window)){
my $query = "SELECT IFNULL($function(datos), 0) AS $function
FROM tagente_datos
WHERE id_agente_modulo = ? AND utimestamp > ?";
my $historical_value = get_db_value($dbh, $query, $alert->{"id_agent_module"}, $window->());
my $activate_alert = 0;
if($function eq "avg"){
# Check if the received value meets the condition compared to the avg.
$activate_alert = eval("$data $condition $historical_value");
}else{
# Check if the hiscorical value meets the condition compared to the val.
$activate_alert = eval("$historical_value $condition $value");
}
# Return $status if the alert is not activated
return $status if !$activate_alert;
}
}
return $status if ($last_status != 1 && $alert->{'type'} eq 'critical');
return $status if ($last_status != 2 && $alert->{'type'} eq 'warning');
return $status if ($last_status != 3 && $alert->{'type'} eq 'unknown');