diff --git a/http_src/constants/metrics-consts.js b/http_src/constants/metrics-consts.js index 484e45506b..7176e9a998 100644 --- a/http_src/constants/metrics-consts.js +++ b/http_src/constants/metrics-consts.js @@ -99,7 +99,7 @@ const sources_types = [ }, { id: "blacklist", //unique id - regex_page_url: "lua\/blacklists_stats", // regex to match url page + regex_page_url: "lua\/admin\/blacklists", // regex to match url page label: i18n("page_stats.source_def.blacklist"), query: "blacklist", f_map_ts_options: (ts_options, ts_group) => { diff --git a/http_src/vue/modal-edit-blacklist.vue b/http_src/vue/modal-edit-blacklist.vue new file mode 100644 index 0000000000..9fe61bfb4b --- /dev/null +++ b/http_src/vue/modal-edit-blacklist.vue @@ -0,0 +1,138 @@ + + + + {{ title_delete }} + + + + + {{ _i18n("name") }} + + + + + + + {{ _i18n("flow_details.url") }} + + + + + + + {{ _i18n("category_lists.enabled") }} + + + + + + + + + {{ _i18n("category") }} + + + + + + {{ _i18n("category_lists.update_frequency") }} + + {{ _i18n("alerts_thresholds_config.daily") }} + {{ _i18n("alerts_thresholds_config.hourly") }} + {{ _i18n("alerts_thresholds_config.manual") }} + + + + + + {{ + _i18n('category_lists.edit_list') }} + + + + + diff --git a/http_src/vue/ntop_vue.js b/http_src/vue/ntop_vue.js index e138c617b8..338b606fc2 100644 --- a/http_src/vue/ntop_vue.js +++ b/http_src/vue/ntop_vue.js @@ -53,6 +53,7 @@ import { default as PageFlowsList } from "./page-flows-list.vue" import { default as PageSNMPInterfaces } from "./page-snmp-interfaces.vue" import { default as PageTopology } from "./page-topology.vue" import { default as PageSNMPDevices } from "./page-snmp-devices.vue" +import { default as PageBlacklists } from "./page-blacklists.vue" // components import { default as AlertInfo } from "./alert-info.vue"; @@ -100,6 +101,7 @@ import { default as ModalEditReport } from "./modal-edit-vs-report.vue"; import { default as ModalAddSNMPDevice } from "./modal-add-snmp-device.vue"; import { default as ModalDeleteSNMPDevice } from "./modal-delete-snmp-device.vue"; import { default as ModalImportSNMPDevices } from "./modal-import-snmp-devices.vue"; +import { default as ModalEditBlacklist } from "./modal-edit-blacklist.vue"; let ntopVue = { // pages @@ -144,6 +146,7 @@ let ntopVue = { NedgeRulesConfig: NedgeRulesConfig, NedgeRepeatersConfig: NedgeRepeatersConfig, + PageBlacklists: PageBlacklists, // Host details pages PageHostDetailsApplications: PageHostDetailsApplications, @@ -206,6 +209,7 @@ let ntopVue = { ModalAddSNMPDevice: ModalAddSNMPDevice, ModalDeleteSNMPDevice: ModalDeleteSNMPDevice, ModalImportSNMPDevices: ModalImportSNMPDevices, + ModalEditBlacklist: ModalEditBlacklist, Vue: Vue, }; diff --git a/http_src/vue/page-blacklists.vue b/http_src/vue/page-blacklists.vue new file mode 100644 index 0000000000..9c02a77c00 --- /dev/null +++ b/http_src/vue/page-blacklists.vue @@ -0,0 +1,308 @@ + + + + + + + {{ item["basic_label"] + }} + + + + + + + + + + + diff --git a/http_src/vue/page-flows-list.vue b/http_src/vue/page-flows-list.vue index 823af9d662..039935ff08 100644 --- a/http_src/vue/page-flows-list.vue +++ b/http_src/vue/page-flows-list.vue @@ -492,4 +492,4 @@ onMounted(() => { // chart.value.update(application_thpt_url + "?" + ntopng_url_manager.get_url_params()); }); -../utilities/formatter-utils.js + diff --git a/httpdocs/tables_config/blacklists.json b/httpdocs/tables_config/blacklists.json new file mode 100644 index 0000000000..55192f267a --- /dev/null +++ b/httpdocs/tables_config/blacklists.json @@ -0,0 +1,127 @@ +{ + "id": "blacklists", + "data_url": "lua/rest/v2/get/system/blacklists/blacklists.lua", + "use_current_page": false, + "enable_search": false, + "paging": false, + "display_empty_rows": true, + "default_sort": { + "column_id": "name", + "sort": 0 + }, + "columns": [ + { + "id": "actions", + "title_i18n": "actions", + "sortable": false, + "sticky": true, + "class": [ + "text-nowrap", + "text-center" + ], + "min-width": "80px", + "render_v_node_type": "button_list", + "button_def_array": [ + { + "id": "chart_blacklist", + "icon": "fas fa-lg fa-chart-area", + "title_i18n": "chart", + "class": [ + "link-button", + "btn-info" + ], + "event_id": "click_chart" + }, + { + "id": "edit_blacklist", + "icon": "fas fa-edit", + "title_i18n": "edit", + "class": [ + "link-button", + "btn-info" + ], + "event_id": "click_edit" + }, + { + "id": "refresh_blacklist", + "icon": "fas fa-sync-alt", + "title_i18n": "refresh", + "class": [ + "link-button", + "btn-info" + ], + "event_id": "click_refresh" + } + ] + }, + { + "title_i18n": "name", + "data_field": "name", + "sortable": true, + "min-width": "155px", + "class": [ + "text-nowrap" + ] + }, + { + "title_i18n": "status", + "data_field": "status", + "sortable": true, + "min-width": "100px", + "class": [ + "text-center", + "text-nowrap" + ] + }, + { + "title_i18n": "category", + "data_field": "category", + "sortable": true, + "min-width": "100px", + "class": [ + "text-nowrap", + "text-center" + ] + }, + { + "title_i18n": "category_lists.update_frequency", + "data_field": "update_frequency", + "sortable": true, + "min-width": "100px", + "class": [ + "text-nowrap", + "text-center" + ] + }, + { + "title_i18n": "category_lists.last_update", + "data_field": "last_update", + "sortable": true, + "min-width": "100px", + "class": [ + "text-nowrap", + "text-center" + ] + }, + { + "title_i18n": "num_entries", + "data_field": "entries", + "sortable": true, + "min-width": "100px", + "class": [ + "text-nowrap", + "text-center" + ] + }, + { + "title_i18n": "graphs.metrics_prefixes.num_hits", + "data_field": "hits", + "sortable": true, + "min-width": "100px", + "class": [ + "text-nowrap", + "text-center" + ] + } + ] +} \ No newline at end of file diff --git a/scripts/locales/en.lua b/scripts/locales/en.lua index 0e30deeb76..6e95496776 100644 --- a/scripts/locales/en.lua +++ b/scripts/locales/en.lua @@ -460,6 +460,7 @@ local lang = { ["notes"] = "NOTES", ["ntop_age_to"] = "24", ["num_different_ports"] = "%{num} ports. None doing %{threshold}%%+ of the traffic.", + ["num_entries"] = "Entries", ["num_uses"] = "Contacts", ["observation_point_alias"] = "Observation Point Alias", ["observation_point_id"] = "Obs. Point ID", diff --git a/scripts/lua/admin/blacklists.lua b/scripts/lua/admin/blacklists.lua new file mode 100644 index 0000000000..c6bdf58530 --- /dev/null +++ b/scripts/lua/admin/blacklists.lua @@ -0,0 +1,45 @@ +-- +-- (C) 2013-24 - ntop.org +-- +-- trace_script_duration = true +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "lua_utils" +local json = require "dkjson" +local template = require "template_utils" +local page_utils = require("page_utils") +local page = _GET["page"] or 'overview' +local base_url = ntop.getHttpPrefix() .. "/lua/admin/blacklists.lua" +sendHTTPContentTypeHeader('text/html') + +page_utils.print_header_and_set_active_menu_entry(page_utils.menu_entries.category_lists) + +dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua") + +page_utils.print_navbar(i18n("category_lists.category_lists"), base_url .. "?", {{ + active = page == "overview" or page == nil, + page_name = "overview", + label = "" +}, { + active = page == "charts", + page_name = "charts", + label = "" +}}) + +if page == "overview" or not page then + local json_context = json.encode({ + csrf = ntop.getRandomCSRFValue() + }) + template.render("pages/vue_page.template", { + vue_page_name = "PageBlacklists", + page_context = json_context + }) +else + local graph_utils = require("graph_utils") + graph_utils.drawNewGraphs({ + ifid = getSystemInterfaceId() + }) +end + +dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua") diff --git a/scripts/lua/admin/edit_category_lists.lua b/scripts/lua/admin/edit_category_lists.lua index 475959d65f..77ce35db8f 100644 --- a/scripts/lua/admin/edit_category_lists.lua +++ b/scripts/lua/admin/edit_category_lists.lua @@ -49,6 +49,11 @@ if _POST["action"] == "edit" then url = string.gsub(url, "http:__", "http://") url = string.gsub(url, "https:__", "https://") + tprint(list_name) + tprint(enabled) + tprint(category) + tprint(url) + tprint(list_update) lists_utils.editList(list_name, { enabled = enabled, diff --git a/scripts/lua/host_details.lua b/scripts/lua/host_details.lua index 7535b84f14..b8f1880845 100644 --- a/scripts/lua/host_details.lua +++ b/scripts/lua/host_details.lua @@ -825,7 +825,7 @@ else i18n("details.label_system_ip") .. '\">') end if (host["is_blacklisted"] == true) then - print(" " .. i18n("details.label_blacklisted_host")) + print(" " .. i18n("details.label_blacklisted_host")) if (host.blacklist_name ~= nil) then print(' (' .. host.blacklist_name .. ')') diff --git a/scripts/lua/inc/menu.lua b/scripts/lua/inc/menu.lua index 3b95049891..73544e56f3 100644 --- a/scripts/lua/inc/menu.lua +++ b/scripts/lua/inc/menu.lua @@ -663,7 +663,7 @@ page_utils.add_menubar_section({ }, { entry = page_utils.menu_entries.category_lists, hidden = not is_admin, - url = '/lua/admin/edit_category_lists.lua' + url = '/lua/admin/blacklists.lua?enabled_status=enabled' }, { entry = page_utils.menu_entries.divider }, { diff --git a/scripts/lua/modules/alert_definitions/other/alert_list_download_failed.lua b/scripts/lua/modules/alert_definitions/other/alert_list_download_failed.lua index 2a8b192311..13f4eee674 100644 --- a/scripts/lua/modules/alert_definitions/other/alert_list_download_failed.lua +++ b/scripts/lua/modules/alert_definitions/other/alert_list_download_failed.lua @@ -39,7 +39,7 @@ function alert_list_download_failed:init(list_name, last_error) self.alert_type_params = { name = list_name, err = last_error, - url = ntop.getHttpPrefix().."/lua/admin/edit_category_lists.lua" + url = ntop.getHttpPrefix().."/lua/admin/blacklists.lua?enabled_status=enabled" } end diff --git a/scripts/lua/modules/page_utils.lua b/scripts/lua/modules/page_utils.lua index 5f71604b7f..22f5882a9d 100644 --- a/scripts/lua/modules/page_utils.lua +++ b/scripts/lua/modules/page_utils.lua @@ -243,6 +243,7 @@ end -- NOTE: this function is called by the web pages in order to -- set the active entry and section and highlight it into the menu function page_utils.print_header_and_set_active_menu_entry(entry, i18n_params, alt_title) + require "locales_utils" entry = entry or page_utils.menu_entries.traffic_dashboard active_section = entry.section diff --git a/scripts/lua/modules/timeseries_info.lua b/scripts/lua/modules/timeseries_info.lua index a5e0d2a640..6a63f4503a 100644 --- a/scripts/lua/modules/timeseries_info.lua +++ b/scripts/lua/modules/timeseries_info.lua @@ -159,20 +159,21 @@ local community_timeseries = {{ } }, { schema = "top:blacklist:hits", + chart_type = "line", id = timeseries_id.blacklist, label = i18n('graphs.metric_labels.top_blacklist_hits'), - priority = 0, + type = "top", + draw_stacked = true, + priority = 2, measure_unit = "hitss", scale = i18n('graphs.metric_labels.blacklist_hits'), - draw_stacked = true, - chart_type = "line", timeseries = { hits = { use_serie_name = true, label = i18n('graphs.metric_labels.blacklist_num_hits'), - color = timeseries_info.get_timeseries_color('') } - } + }, + default_visible = true }, { schema = "iface:new_flows", id = timeseries_id.iface, @@ -2111,17 +2112,8 @@ local function add_top_blacklist_hits_timeseries(tags, timeseries) end for _, serie in pairs(series or {}) do tmp_tags.blacklist_name = serie.blacklist_name - local tot = 0 - local tot_serie = ts_utils.queryTotal("blacklist:hits", tags.epoch_begin, tags.epoch_end, tmp_tags) - for _, value in pairs(tot_serie or {}) do - tot = tot + tonumber(value) - end - -- Uncomment to return only timeseries with values - -- if tot <= 0 then - -- return - -- end timeseries[#timeseries + 1] = { - schema = "top:blacklist:hits", + schema = "blacklist:hits", id = timeseries_id.blacklist, group = i18n("graphs.metric_labels.blacklist_num_hits"), priority = 0, @@ -2134,7 +2126,6 @@ local function add_top_blacklist_hits_timeseries(tags, timeseries) hits = { use_serie_name = true, label = i18n('graphs.metric_labels.blacklist_num_hits'), - color = timeseries_info.get_timeseries_color('') } } } diff --git a/scripts/lua/rest/v2/edit/system/edit_blacklist.lua b/scripts/lua/rest/v2/edit/system/edit_blacklist.lua new file mode 100644 index 0000000000..e2a3480558 --- /dev/null +++ b/scripts/lua/rest/v2/edit/system/edit_blacklist.lua @@ -0,0 +1,39 @@ +-- +-- (C) 2013-24 - ntop.org +-- +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "ntop_utils" +require "http_lint" +local rest_utils = require "rest_utils" +local lists_utils = require "lists_utils" + +local enabled = _POST["list_enabled"] +local list_name = _POST["list_name"] +local category = tonumber(_POST["category"]) +local url = _POST["url"] +local list_update = tonumber(_POST["list_update"]) + +if enabled == "on" then + enabled = true +else + enabled = false +end +if isEmptyString(enabled) or isEmptyString(list_name) or isEmptyString(category) or isEmptyString(url) or + isEmptyString(list_update) then + rest_utils.answer(rest_utils.consts.err.bad_content) + return +end + +url = string.gsub(url, "http:__", "http://") +url = string.gsub(url, "https:__", "https://") + +lists_utils.editList(list_name, { + enabled = enabled, + category = nil, + url = url, + update_interval = list_update +}) + +rest_utils.answer(rest_utils.consts.success.ok) diff --git a/scripts/lua/rest/v2/get/flow/active_list.lua b/scripts/lua/rest/v2/get/flow/active_list.lua index 4542967b4d..c3a66df30a 100644 --- a/scripts/lua/rest/v2/get/flow/active_list.lua +++ b/scripts/lua/rest/v2/get/flow/active_list.lua @@ -88,6 +88,13 @@ local rsp = {} local flows_stats = interface.getFlowsInfo(flows_filter["hostFilter"], flows_filter, flows_filter["talkingWith"], flows_filter["client"], flows_filter["server"], flows_filter["flow_info"]) +if not flows_stats then + rest_utils.extended_answer(rest_utils.consts.success.ok, {}, { + ["recordsTotal"] = 0 + }) + return +end + for _, value in ipairs(flows_stats.flows) do local record = {} local key = value["ntopng.key"] diff --git a/scripts/lua/rest/v2/get/system/blacklists/blacklists.lua b/scripts/lua/rest/v2/get/system/blacklists/blacklists.lua new file mode 100644 index 0000000000..6a445f71f9 --- /dev/null +++ b/scripts/lua/rest/v2/get/system/blacklists/blacklists.lua @@ -0,0 +1,63 @@ +-- +-- (C) 2013-24 - ntop.org +-- +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "ntop_utils" +require "lua_utils_get" +local rest_utils = require "rest_utils" +local lists_utils = require "lists_utils" + +local rsp = {} +local category_filter = _GET["category"] +local enabled_status = _GET["enabled_status"] +local lists = lists_utils.getCategoryLists() + +-- ################################################ + +local function getListStatusLabel(list) + if not list.enabled then + return "disabled" + end + + if list.status.last_error then + return "error" + end + + return "enabled" +end + +-- ################################################ + +for list_name, list in pairs(lists) do + local catname = interface.getnDPICategoryName(tonumber(list.category)) + + if ((not isEmptyString(category_filter)) and (category_filter ~= catname)) then + goto continue + end + + if enabled_status == "disabled" and list.enabled then + goto continue + elseif enabled_status == "enabled" and not list.enabled then + goto continue + end + + rsp[#rsp + 1] = { + name = list_name, + status = getListStatusLabel(list), + category = getCategoryLabel(catname, list.category), + update_frequency = list.update_interval, + last_update = list.status.last_update, + entries = list.status.num_hosts, + hits = list.status.num_hits.current, + url = list.url, + category_id = list.category + } + + ::continue:: +end + +rest_utils.extended_answer(rest_utils.consts.success.ok, rsp, { + ["recordsTotal"] = 0 +}) diff --git a/scripts/lua/rest/v2/get/system/blacklists/blacklists_filters.lua b/scripts/lua/rest/v2/get/system/blacklists/blacklists_filters.lua new file mode 100644 index 0000000000..f96ad49449 --- /dev/null +++ b/scripts/lua/rest/v2/get/system/blacklists/blacklists_filters.lua @@ -0,0 +1,61 @@ +-- +-- (C) 2013-24 - ntop.org +-- +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "lua_utils_get" +local rest_utils = require "rest_utils" +local lists_utils = require "lists_utils" + +local rsp = {} +local lists = lists_utils.getCategoryLists() +local list = {{ + key = "enabled_status", + value = "enabled", + label = i18n("category_lists.enabled") +}, { + key = "enabled_status", + value = "disabled", + label = i18n("disabled") +}, { + key = "enabled_status", + value = "all", + label = i18n("all") +}} + +rsp[#rsp + 1] = { + action = "enabled_status", + label = i18n("status"), + name = "enabled_status", + value = list +} + +list = {{ + key = "category", + value = "", + label = i18n("all") +}} +local category_list = {} +for list_name, list in pairsByKeys(lists) do + local catname = interface.getnDPICategoryName(tonumber(list.category)) + local category = getCategoryLabel(catname, list.category) + category_list[category] = (category_list[category] or 0) + 1 +end + +for category, _ in pairs(category_list) do + list[#list + 1] = { + key = "category", + value = category, + label = category + } +end + +rsp[#rsp + 1] = { + action = "category", + label = i18n("category"), + name = "category", + value = list +} + +rest_utils.answer(rest_utils.consts.success.ok, rsp) diff --git a/scripts/lua/rest/v2/get/system/blacklists/update_blacklist.lua b/scripts/lua/rest/v2/get/system/blacklists/update_blacklist.lua new file mode 100644 index 0000000000..62c429c874 --- /dev/null +++ b/scripts/lua/rest/v2/get/system/blacklists/update_blacklist.lua @@ -0,0 +1,18 @@ +-- +-- (C) 2013-24 - ntop.org +-- +local dirs = ntop.getDirs() +package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path + +require "ntop_utils" +local rest_utils = require "rest_utils" +local lists_utils = require "lists_utils" +local list_name = _GET["list_name"] + +if isEmptyString(list_name) then + rest_utils.answer(rest_utils.consts.err.bad_content) + return +end +lists_utils.updateList(list_name) + +rest_utils.answer(rest_utils.consts.success.ok) \ No newline at end of file