From 9fd08c928a2b6a3c5a82edf6835452a906887110 Mon Sep 17 00:00:00 2001 From: Jonathan <jonathan.leon@pandorafms.com> Date: Mon, 19 Jun 2023 16:14:21 +0200 Subject: [PATCH] #11573 network filters --- pandora_console/extras/mr/65.sql | 21 + pandora_console/include/functions_netflow.php | 18 +- .../operation/network/network_report.php | 359 +++++++++++++----- .../operation/network/network_usage_map.php | 140 ++++++- pandora_console/pandoradb.sql | 24 ++ 5 files changed, 453 insertions(+), 109 deletions(-) create mode 100644 pandora_console/extras/mr/65.sql diff --git a/pandora_console/extras/mr/65.sql b/pandora_console/extras/mr/65.sql new file mode 100644 index 0000000000..7f7a423fcf --- /dev/null +++ b/pandora_console/extras/mr/65.sql @@ -0,0 +1,21 @@ +START TRANSACTION; + +CREATE TABLE IF NOT EXISTS `tnetwork_explorer_filter` ( +`id` INT NOT NULL, +`filter_name` VARCHAR(45) NULL, +`top` VARCHAR(45) NULL, +`action` VARCHAR(45) NULL, +`advanced_filter` TEXT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +CREATE TABLE IF NOT EXISTS `tnetwork_usage_filter` ( +`id` INT NOT NULL auto_increment, +`filter_name` VARCHAR(45) NULL, +`top` VARCHAR(45) NULL, +`action` VARCHAR(45) NULL, +`advanced_filter` TEXT NULL, +PRIMARY KEY (`id`) +) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +COMMIT; diff --git a/pandora_console/include/functions_netflow.php b/pandora_console/include/functions_netflow.php index 66e1ad1a9f..7d7000ae5b 100644 --- a/pandora_console/include/functions_netflow.php +++ b/pandora_console/include/functions_netflow.php @@ -1734,7 +1734,12 @@ function netflow_get_top_summary( switch ($top_action) { case 'listeners': if (empty(!$filter)) { - $netflow_filter['ip_src'] = $filter; + if (!is_array($filter)) { + $netflow_filter['ip_src'] = $filter; + } else { + $netflow_filter['ip_src'] = $filter['ip']; + $netflow_filter['advanced_filter'] = $filter['advanced_filter']; + } } $sort = 'dstip'; @@ -1742,7 +1747,12 @@ function netflow_get_top_summary( case 'talkers': if (empty(!$filter)) { - $netflow_filter['ip_dst'] = $filter; + if (!is_array($filter)) { + $netflow_filter['ip_dst'] = $filter; + } else { + $netflow_filter['ip_dst'] = $filter['ip']; + $netflow_filter['advanced_filter'] = $filter['advanced_filter']; + } } $sort = 'srcip'; @@ -2069,7 +2079,7 @@ function netflow_aggregate_is_ip($aggregate) * * @return array With map structure. */ -function netflow_build_map_data($start_date, $end_date, $top, $aggregate) +function netflow_build_map_data($start_date, $end_date, $top, $aggregate, $advanced_filter='') { // Pass an empty filter data structure. $data = netflow_get_relationships_raw_data( @@ -2083,7 +2093,7 @@ function netflow_build_map_data($start_date, $end_date, $top, $aggregate) 'ip_src' => '', 'dst_port' => '', 'src_port' => '', - 'advanced_filter' => '', + 'advanced_filter' => $advanced_filter, 'router_ip' => '', ], $top, diff --git a/pandora_console/operation/network/network_report.php b/pandora_console/operation/network/network_report.php index 5d036df61a..c4e9a01365 100644 --- a/pandora_console/operation/network/network_report.php +++ b/pandora_console/operation/network/network_report.php @@ -39,10 +39,26 @@ if (! check_acl($config['id_user'], 0, 'AR')) { exit; } +// Ajax callbacks. +if (is_ajax() === true) { + $get_filter_values = get_parameter('get_filter_values', 0); + // Get values of the current network filter. + if ($get_filter_values) { + $id = get_parameter('id'); + $filter_values = db_get_row_filter('tnetwork_explorer_filter', ['id' => $id]); + // Decode HTML entities. + $filter_values['advanced_filter'] = io_safe_output($filter_values['advanced_filter']); + echo json_encode($filter_values); + } + + return; +} + // Include JS timepicker. ui_include_time_picker(); // Query params and other initializations. +$filter_id = (int) get_parameter('filter_id', 0); $time_greater = get_parameter('time_greater', date(TIME_FORMAT)); $date_greater = get_parameter('date_greater', date(DATE_FORMAT)); $utimestamp_greater = strtotime($date_greater.' '.$time_greater); @@ -59,6 +75,13 @@ $top = (int) get_parameter('top', 10); $main_value = ((bool) get_parameter('remove_filter', 0)) ? '' : get_parameter('main_value', ''); if (is_numeric($main_value) && !in_array($action, ['udp', 'tcp'])) { $main_value = ''; +} else { + $filter['ip'] = $main_value; +} + +$advanced_filter = get_parameter('advanced_filter', ''); +if ($advanced_filter !== '') { + $filter['advanced_filter'] = $advanced_filter; } $order_by = get_parameter('order_by', 'bytes'); @@ -66,30 +89,143 @@ if (!in_array($order_by, ['bytes', 'pkts', 'flows'])) { $order_by = 'bytes'; } -$style_end = ($is_period) ? 'display: none;' : ''; -$style_period = ($is_period) ? '' : 'display: none;'; +$save = get_parameter('save_button', ''); +$update = get_parameter('update_button', ''); + +// Save user defined filter. +if ($save != '' && check_acl($config['id_user'], 0, 'AW')) { + // Save filter args. + $data['filter_name'] = get_parameter('filter_name'); + $data['top'] = $top; + $data['action'] = $action; + $data['advanced_filter'] = $advanced_filter; + + + $filter_id = db_process_sql_insert('tnetwork_explorer_filter', $data); + if ($filter_id === false) { + $filter_id = 0; + ui_print_error_message(__('Error creating filter')); + } else { + ui_print_success_message(__('Filter created successfully')); + } +} else if ($update != '' && check_acl($config['id_user'], 0, 'AW')) { + // Update current filter. + // Do not update the filter name and group. + $data['top'] = $top; + $data['action'] = $action; + $data['advanced_filter'] = $advanced_filter; + + $result = db_process_sql_update( + 'tnetwork_explorer_filter', + $data, + ['id' => $filter_id] + ); + ui_print_result_message( + $result, + __('Filter updated successfully'), + __('Error updating filter') + ); +} // Build the table. -$table = new stdClass(); -$table->class = 'filter-table-adv'; -$table->width = '100%'; -$table->data = []; +$filterTable = new stdClass(); +$filterTable->id = ''; +$filterTable->class = 'filter-table-adv'; +$filterTable->size = []; +$filterTable->size[0] = '33%'; +$filterTable->size[1] = '33%'; +$filterTable->size[2] = '33%'; +$filterTable->data = []; -$table->data[0][] = html_print_label_input_block( - __('Data to show'), - html_print_select( - network_get_report_actions(false), - 'action', - $action, +$filterTable->data[0][0] = html_print_label_input_block( + __('Interval'), + html_print_extended_select_for_time( + 'period', + $period, '', '', 0, + false, + true + ), + [ 'div_id' => 'period_container' ] +); + +$filterTable->data[0][0] .= html_print_label_input_block( + __('Start date'), + html_print_div( + [ + 'class' => '', + 'content' => html_print_input_text( + 'date_lower', + $date_lower, + false, + 13, + 10, + true + ).html_print_image( + 'images/calendar_view_day.png', + true, + [ + 'alt' => 'calendar', + 'class' => 'main_menu_icon invert_filter', + ] + ).html_print_input_text( + 'time_lower', + $time_lower, + false, + 10, + 8, + true + ), + ], + true + ), + [ 'div_id' => 'end_date_container' ] +); + +$filterTable->data[0][1] = html_print_label_input_block( + __('End date'), + html_print_div( + [ + 'content' => html_print_input_text( + 'date', + $date_greater, + false, + 13, + 10, + true + ).html_print_image( + 'images/calendar_view_day.png', + true, + ['alt' => 'calendar'] + ).html_print_input_text( + 'time', + $time_greater, + false, + 10, + 8, + true + ), + ], true ) ); -$table->data[0][] = html_print_label_input_block( - __('Number of result to show'), +$filterTable->data[0][2] = html_print_label_input_block( + __('Defined period'), + html_print_checkbox_switch( + 'is_period', + 1, + ($is_period === true) ? 1 : 0, + true, + false, + 'nf_view_click_period()' + ) +); + +$filterTable->data[1][] = html_print_label_input_block( + __('Results to show'), html_print_select( [ '5' => 5, @@ -110,95 +246,62 @@ $table->data[0][] = html_print_label_input_block( ) ); -$table->data[1][] = html_print_label_input_block( - __('Start date'), - html_print_div( - [ - 'id' => 'end_date_container', - 'content' => html_print_input_text( - 'date_lower', - $date_lower, - '', - 10, - 10, - true - ).html_print_input_text( - 'time_lower', - $time_lower, - '', - 7, - 8, - true - ), - ], - true - ).html_print_div( - [ - 'id' => 'period_container', - 'style' => 'display: none;', - 'content' => html_print_label_input_block( - '', - html_print_extended_select_for_time( - 'period', - $period, - '', - '', - 0, - false, - true - ), - ), - ], +$filterTable->data[1][] = html_print_label_input_block( + __('Data to show'), + html_print_select( + network_get_report_actions(), + 'action', + $action, + '', + '', + 0, true ) ); -$table->data[1][] = html_print_label_input_block( - __('End date'), - html_print_div( - [ - 'id' => '', - 'class' => '', - 'content' => html_print_input_text( - 'date_greater', - $date_greater, - '', - 10, - 10, - true - ).html_print_input_text( - 'time_greater', - $time_greater, - '', - 7, - 8, - true - ), - ], - true - ) +$advanced_toggle = new stdClass(); +$advanced_toggle->class = 'filter-table-adv'; +$advanced_toggle->size = []; +$advanced_toggle->size[0] = '50%'; +$advanced_toggle->size[1] = '50%'; +$advanced_toggle->width = '100%'; +$user_groups = users_get_groups($config['id_user'], 'AR', $own_info['is_admin'], true); +$user_groups[0] = 0; +// Add all groups. +$sql = 'SELECT * FROM tnetwork_explorer_filter'; +$advanced_toggle->data[0][0] = html_print_label_input_block( + __('Load Filter'), + html_print_select_from_sql($sql, 'filter_id', $filter_id, '', __('Select a filter'), 0, true, false, true, false, 'width:100%;') ); - -$table->data[2][] = html_print_label_input_block( - __('Defined period'), - html_print_checkbox_switch( - 'is_period', - 1, - ($is_period === true) ? 1 : 0, +$advanced_toggle->data[0][1] = html_print_label_input_block( + __('Filter name'), + html_print_input_text('filter_name', '', false, 40, 45, true, false, false, '', 'w100p') +); +$advanced_toggle->colspan[1][0] = 2; +$advanced_toggle->data[1][0] = html_print_label_input_block( + __('Filter').ui_print_help_icon('pcap_filter', true), + html_print_textarea('advanced_filter', 4, 10, $advanced_filter, 'style="width:100%"', true) +); +$filterTable->colspan[2][0] = 3; +$filterTable->data[2][0] = html_print_label_input_block( + '', + ui_toggle( + html_print_table($advanced_toggle, true), + __('Advanced'), + '', + '', true, - false, - 'network_report_click_period(event)' + true, + '', + 'white-box-content', + 'box-flat white_table_graph' ) ); -echo '<form method="post">'; -html_print_input_hidden('order_by', $order_by); -if (empty($main_value) === false) { - html_print_input_hidden('main_value', $main_value); -} - -$outputTable = html_print_table($table, true); -$outputTable .= html_print_div( +$filterInputTable = '<form method="POST">'; +$filterInputTable .= html_print_input_hidden('order_by', $order_by); +$filterInputTable .= html_print_table($filterTable, true); +$filterInputTable .= html_print_div( [ 'class' => 'action-buttons-right-forced', 'content' => html_print_submit_button( @@ -210,19 +313,48 @@ $outputTable .= html_print_div( 'mode' => 'mini', ], true + ).html_print_submit_button( + __('Save as new filter'), + 'save_button', + false, + [ + 'icon' => 'load', + 'onClick' => 'return defineFilterName();', + 'mode' => 'mini secondary', + 'class' => 'mrgn_right_10px', + ], + true + ).html_print_submit_button( + __('Update current filter'), + 'update_button', + false, + [ + 'icon' => 'load', + 'mode' => 'mini secondary', + 'class' => 'mrgn_right_10px', + ], + true ), ], true ); +$filterInputTable .= html_print_div( + [ + 'class' => 'action-buttons', + 'content' => $netflow_button, + ], + true +); +$filterInputTable .= '</form>'; ui_toggle( - $outputTable, - '<span class="subsection_header_title">'.__('Filters').'</span>', - __('Filters'), - '', + $filterInputTable, + '<span class="subsection_header_title">'.__('Filter').'</span>', + __('Filter'), + 'search', true, false, '', - 'white-box-content', + 'white-box-content no_border', 'box-flat white_table_graph fixed_filter_bar' ); html_print_action_buttons( @@ -246,7 +378,7 @@ $data = netflow_get_top_summary( $action, $utimestamp_lower, $utimestamp_greater, - $main_value, + $filter, $order_by ); @@ -450,6 +582,26 @@ if (empty($data)) { ?> <script> +$(document).ready(function(){ + nf_view_click_period(); + + $('#filter_id').change(function(){ + jQuery.post ( + "ajax.php", + { + "page" : "operation/network/network_report", + "get_filter_values" : 1, + "id": $(this).val(), + }, + function (data) { + $('#action').val(data.action).trigger('change'); + $('#top').val(data.top).trigger('change'); + $('#textarea_advanced_filter').val(data.advanced_filter); + $('select#filter_id').select2('close'); + }, 'json'); + }); +}); + // Configure jQuery timepickers. $("#text-time_lower, #text-time_greater").timepicker({ showSecond: true, @@ -472,4 +624,11 @@ function network_report_click_period(event) { document.getElementById('period_container').style.display = !is_period ? 'none' : 'block'; document.getElementById('end_date_container').style.display = is_period ? 'none' : 'block'; } + +function nf_view_click_period() { + var is_period = document.getElementById('checkbox-is_period').checked; + + document.getElementById('period_container').style.display = !is_period ? 'none' : 'flex'; + document.getElementById('end_date_container').style.display = is_period ? 'none' : 'flex'; +} </script> diff --git a/pandora_console/operation/network/network_usage_map.php b/pandora_console/operation/network/network_usage_map.php index 7e3964b277..76a5c396ad 100644 --- a/pandora_console/operation/network/network_usage_map.php +++ b/pandora_console/operation/network/network_usage_map.php @@ -34,6 +34,21 @@ global $config; check_login(); +// Ajax callbacks. +if (is_ajax() === true) { + $get_filter_values = get_parameter('get_filter_values', 0); + // Get values of the current network filter. + if ($get_filter_values) { + $id = get_parameter('id'); + $filter_values = db_get_row_filter('tnetwork_usage_filter', ['id' => $id]); + // Decode HTML entities. + $filter_values['advanced_filter'] = io_safe_output($filter_values['advanced_filter']); + echo json_encode($filter_values); + } + + return; +} + // Header. ui_print_standard_header( __('Network usage map'), @@ -76,6 +91,7 @@ $is_period = (bool) get_parameter('is_period', false); $period = (int) get_parameter('period', SECONDS_1HOUR); $time_lower = get_parameter('time_lower', date(TIME_FORMAT, ($utimestamp_greater - $period))); $date_lower = get_parameter('date_lower', date(DATE_FORMAT, ($utimestamp_greater - $period))); +$advanced_filter = get_parameter('advanced_filter', ''); $utimestamp_lower = ($is_period) ? ($utimestamp_greater - $period) : strtotime($date_lower.' '.$time_lower); if (!$is_period) { $period = ($utimestamp_greater - $utimestamp_lower); @@ -88,6 +104,44 @@ if (in_array($order_by, ['bytes', 'pkts', 'flows']) === false) { $order_by = 'bytes'; } +$save = get_parameter('save_button', ''); +$update = get_parameter('update_button', ''); + +// Save user defined filter. +if ($save != '' && check_acl($config['id_user'], 0, 'AW')) { + // Save filter args. + $data['filter_name'] = get_parameter('filter_name'); + $data['top'] = $top; + $data['action'] = $action; + $data['advanced_filter'] = $advanced_filter; + + + $filter_id = db_process_sql_insert('tnetwork_usage_filter', $data); + if ($filter_id === false) { + $filter_id = 0; + ui_print_error_message(__('Error creating filter')); + } else { + ui_print_success_message(__('Filter created successfully')); + } +} else if ($update != '' && check_acl($config['id_user'], 0, 'AW')) { + // Update current filter. + // Do not update the filter name and group. + $data['top'] = $top; + $data['action'] = $action; + $data['advanced_filter'] = $advanced_filter; + + $result = db_process_sql_update( + 'tnetwork_usage_filter', + $data, + ['id' => $filter_id] + ); + ui_print_result_message( + $result, + __('Filter updated successfully'), + __('Error updating filter') + ); +} + if ((bool) $config['activate_netflow'] === true) { $netflow_button = html_print_submit_button( __('Show netflow map'), @@ -95,6 +149,27 @@ if ((bool) $config['activate_netflow'] === true) { false, ['icon' => 'update'], true + ).html_print_submit_button( + __('Save as new filter'), + 'save_button', + false, + [ + 'icon' => 'load', + 'onClick' => 'return defineFilterName();', + 'mode' => 'mini secondary', + 'class' => 'mrgn_right_10px', + ], + true + ).html_print_submit_button( + __('Update current filter'), + 'update_button', + false, + [ + 'icon' => 'load', + 'mode' => 'mini secondary', + 'class' => 'mrgn_right_10px', + ], + true ); } else { $netflow_button = ''; @@ -232,6 +307,44 @@ $filterTable->data[1][] = html_print_label_input_block( ) ); +$advanced_toggle = new stdClass(); +$advanced_toggle->class = 'filter-table-adv'; +$advanced_toggle->size = []; +$advanced_toggle->size[0] = '50%'; +$advanced_toggle->size[1] = '50%'; +$advanced_toggle->width = '100%'; +$user_groups = users_get_groups($config['id_user'], 'AR', $own_info['is_admin'], true); +$user_groups[0] = 0; +$sql = 'SELECT * FROM tnetwork_usage_filter'; +$advanced_toggle->data[0][0] = html_print_label_input_block( + __('Load Filter'), + html_print_select_from_sql($sql, 'filter_id', $filter_id, '', __('Select a filter'), 0, true, false, true, false, 'width:100%;') +); +$advanced_toggle->data[0][1] = html_print_label_input_block( + __('Filter name'), + html_print_input_text('filter_name', '', false, 40, 45, true, false, false, '', 'w100p') +); +$advanced_toggle->colspan[1][0] = 2; +$advanced_toggle->data[1][0] = html_print_label_input_block( + __('Filter').ui_print_help_icon('pcap_filter', true), + html_print_textarea('advanced_filter', 4, 10, $advanced_filter, 'style="width:100%"', true) +); +$filterTable->colspan[2][0] = 3; +$filterTable->data[2][0] = html_print_label_input_block( + '', + ui_toggle( + html_print_table($advanced_toggle, true), + __('Advanced'), + '', + '', + true, + true, + '', + 'white-box-content', + 'box-flat white_table_graph' + ) +); + $filterInputTable = '<form method="POST">'; $filterInputTable .= html_print_input_hidden('order_by', $order_by); $filterInputTable .= html_print_table($filterTable, true); @@ -263,7 +376,8 @@ if ((bool) get_parameter('update_netflow') === true) { $utimestamp_lower, $utimestamp_greater, $top, - ($action === 'talkers') ? 'srcip' : 'dstip' + ($action === 'talkers') ? 'srcip' : 'dstip', + $advanced_filter ); $has_data = !empty($map_data['nodes']); } @@ -283,10 +397,26 @@ if ($has_data === true) { </style> <script> - $(document).ready(function(){ - nf_view_click_period(); - } - ); +$(document).ready(function(){ + nf_view_click_period(); + + $('#filter_id').change(function(){ + jQuery.post ( + "ajax.php", + { + "page" : "operation/network/network_usage_map", + "get_filter_values" : 1, + "id": $(this).val(), + }, + function (data) { + $('#action').val(data.action).trigger('change'); + $('#top').val(data.top).trigger('change'); + $('#textarea_advanced_filter').val(data.advanced_filter); + $('select#filter_id').select2('close'); + }, 'json'); + }); +}); + // Configure jQuery timepickers. $("#text-time_lower, #text-time_greater").timepicker({ showSecond: true, diff --git a/pandora_console/pandoradb.sql b/pandora_console/pandoradb.sql index 8706e37fed..c802e4f4bf 100644 --- a/pandora_console/pandoradb.sql +++ b/pandora_console/pandoradb.sql @@ -4323,3 +4323,27 @@ CREATE TABLE IF NOT EXISTS `tsesion_filter_log_viewer` ( `graph_type` INT NULL, PRIMARY KEY (`id_filter`) ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +-- --------------------------------------------------------------------- +-- Table `tnetwork_explorer_filter` +-- --------------------------------------------------------------------- +CREATE TABLE IF NOT EXISTS `tnetwork_explorer_filter` ( + `id` INT NOT NULL, + `filter_name` VARCHAR(45) NULL, + `top` VARCHAR(45) NULL, + `action` VARCHAR(45) NULL, + `advanced_filter` TEXT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; + +-- --------------------------------------------------------------------- +-- Table `tnetwork_usage_filter` +-- --------------------------------------------------------------------- + CREATE TABLE IF NOT EXISTS `tnetwork_usage_filter` ( + `id` INT NOT NULL auto_increment, + `filter_name` VARCHAR(45) NULL, + `top` VARCHAR(45) NULL, + `action` VARCHAR(45) NULL, + `advanced_filter` TEXT NULL, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; \ No newline at end of file