mirror of
https://github.com/ntop/ntopng.git
synced 2026-04-29 15:39:33 +00:00
[VS] Fix notification sending at the end of periodic scan or scan all. (#7937)
This commit is contained in:
parent
9facf5bb79
commit
181f8a8178
3 changed files with 286 additions and 36 deletions
|
|
@ -39,12 +39,23 @@ package.path = dirs.installdir .. "/scripts/lua/modules/recipients/?.lua;" .. pa
|
|||
|
||||
require "lua_utils" -- used by tprint (debug)
|
||||
|
||||
local host_to_scan_key = "ntopng.prefs.host_to_scan"
|
||||
local host_to_scan_periodicity_key = "ntopng.prefs.host_to_scan.periodicity_scan"
|
||||
local host_scannned_count_key = "ntopng.prefs.host_to_scan.count_scanned"
|
||||
local host_scan_queue_key = "ntopng.vs_scan_queue"
|
||||
local scanned_hosts_changes_key = "ntopng.alerts.scanned_hosts_changes"
|
||||
local host_in_scanning_hash_key = "ntopng.prefs.host_to_scan.in_scanning"
|
||||
local host_to_scan_key = "ntopng.prefs.host_to_scan"
|
||||
local host_to_scan_periodicity_key = "ntopng.prefs.host_to_scan.periodicity_scan"
|
||||
local host_to_scan_all_key = "ntopng.prefs.host_to_scan.scan_all"
|
||||
local host_scannned_count_key = "ntopng.prefs.host_to_scan.count_scanned"
|
||||
local host_scan_queue_key = "ntopng.vs_scan_queue"
|
||||
local scanned_hosts_changes_key = "ntopng.alerts.scanned_hosts_changes"
|
||||
local host_in_scanning_hash_key = "ntopng.prefs.host_to_scan.in_scanning"
|
||||
|
||||
-- redis keys for periodic scan info
|
||||
local host_periodic_scan_cve_num_key = "ntopng.prefs.host_to_scan.periodicity_scan.info.cve_num"
|
||||
local host_periodic_scan_udp_ports_key = "ntopng.prefs.host_to_scan.periodicity_scan.info.udp_ports"
|
||||
local host_periodic_scan_tcp_ports_key = "ntopng.prefs.host_to_scan.periodicity_scan.info.tcp_ports"
|
||||
|
||||
-- redis keys for scan all info
|
||||
local host_scan_all_cve_num_key = "ntopng.prefs.host_to_scan.scan_all.info.cve_num"
|
||||
local host_scan_all_udp_ports_key = "ntopng.prefs.host_to_scan.scan_all.info.udp_ports"
|
||||
local host_scan_all_tcp_ports_key = "ntopng.prefs.host_to_scan.scan_all.info.tcp_ports"
|
||||
|
||||
local json = require("dkjson")
|
||||
local format_utils = require("format_utils")
|
||||
|
|
@ -614,6 +625,59 @@ local function save_scanning_host(scan_info)
|
|||
ntop.setHashCache(host_in_scanning_hash_key, host_to_scan_hash_key, json.encode(scan_info))
|
||||
end
|
||||
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to select correctly redis keys on periodic or scan all
|
||||
local function get_counter_periodic_all_scan_keys(is_periodic)
|
||||
|
||||
if (is_periodic) then
|
||||
return host_periodic_scan_cve_num_key,host_periodic_scan_udp_ports_key,host_periodic_scan_tcp_ports_key
|
||||
else
|
||||
return host_scan_all_cve_num_key,host_scan_all_udp_ports_key,host_scan_all_tcp_ports_key
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to update counters of periodically scan or scan all
|
||||
-- @param is_periodic (true -> is a periodic scan, false -> is a scan all)
|
||||
local function update_periodicity_or_all_scan_info(is_periodic, new_item)
|
||||
|
||||
|
||||
-- select correctly redis keys
|
||||
local cve_num_redis_key, udp_ports_redis_key, tcp_ports_redis_key = get_counter_periodic_all_scan_keys(is_periodic)
|
||||
if (new_item.num_vulnerabilities_found ~= nil) then
|
||||
local cve_num_string = ntop.getCache(cve_num_redis_key)
|
||||
local old_saved_cve_num = tonumber(cve_num_string or 0)
|
||||
local new_cve_num = new_item.num_vulnerabilities_found + old_saved_cve_num
|
||||
if (new_cve_num ~= old_saved_cve_num) then
|
||||
ntop.setCache(cve_num_redis_key, tostring(new_cve_num))
|
||||
end
|
||||
end
|
||||
|
||||
if (new_item.udp_ports ~= nil) then
|
||||
local udp_ports_num_string = ntop.getCache(udp_ports_redis_key)
|
||||
local old_udp_ports_num = tonumber(udp_ports_num_string or 0)
|
||||
local new_udp_ports_num = old_udp_ports_num + new_item.udp_ports
|
||||
if (old_udp_ports_num ~= new_udp_ports_num) then
|
||||
ntop.setCache(udp_ports_redis_key, tostring(new_udp_ports_num))
|
||||
end
|
||||
end
|
||||
|
||||
if (new_item.tcp_ports ~= nil) then
|
||||
local tcp_ports_num_string = ntop.getCache(tcp_ports_redis_key)
|
||||
local old_tcp_ports_num = tonumber(tcp_ports_num_string or 0)
|
||||
|
||||
local new_tcp_ports_num = old_tcp_ports_num + new_item.tcp_ports
|
||||
if (old_tcp_ports_num ~= new_tcp_ports_num) then
|
||||
ntop.setCache(tcp_ports_redis_key, tostring(new_tcp_ports_num))
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to restore scanning host
|
||||
|
|
@ -632,7 +696,9 @@ function vs_utils.restore_host_to_scan()
|
|||
ntop.lpushCache(host_scan_queue_key, hash_value_string)
|
||||
|
||||
-- set status to scheduled
|
||||
vs_utils.set_status_scan(host_info_to_restore.scan_type, host_info_to_restore.host, host_info_to_restore.ports, host_info_to_restore.id, nil, vs_utils.scan_status.scheduled)
|
||||
vs_utils.set_status_scan( host_info_to_restore.scan_type, host_info_to_restore.host, host_info_to_restore.ports,
|
||||
host_info_to_restore.id, host_info_to_restore.is_periodicity, host_info_to_restore.is_all,
|
||||
vs_utils.scan_status.scheduled)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -766,6 +832,15 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
|
|||
new_item.scan_frequency = old_data.scan_frequency
|
||||
end
|
||||
|
||||
-- the is_periodicity param and is_all param are set outside the save_host_to_scan into the set_status method
|
||||
if (old_data and old_data.is_periodicity ~= nil) then
|
||||
new_item.is_periodicity = old_data.is_periodicity
|
||||
end
|
||||
|
||||
if (old_data and old_data.is_all ~= nil) then
|
||||
new_item.is_all = old_data.is_all
|
||||
end
|
||||
|
||||
if(scan_result ~= nil) then
|
||||
local handle = io.open(get_report_path(scan_type, host), "w")
|
||||
local result = handle:write(scan_result)
|
||||
|
|
@ -795,7 +870,14 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
|
|||
|
||||
local counts = vs_utils.update_ts_counters()
|
||||
|
||||
vs_utils.notify_end_periodicity()
|
||||
--vs_utils.notify_end_periodicity()
|
||||
if (new_item.is_periodicity) then
|
||||
update_periodicity_or_all_scan_info(true, new_item)
|
||||
end
|
||||
|
||||
if (new_item.is_all) then
|
||||
update_periodicity_or_all_scan_info(false, new_item)
|
||||
end
|
||||
|
||||
remove_scanning_host({host=host, scan_type=scan_type, ports=ports})
|
||||
|
||||
|
|
@ -838,19 +920,111 @@ function vs_utils.update_ts_counters()
|
|||
return response
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to format num for emails
|
||||
-- @param case: 0 - cve, 1 - udp, 2 - tcp
|
||||
local function format_num_for_email(num, case)
|
||||
if (case == 0) then
|
||||
-- cve
|
||||
if (num == 0) then
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.no_cves"))
|
||||
else
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.num_cves", {num = num}))
|
||||
end
|
||||
elseif (case == 1) then
|
||||
-- udp
|
||||
if (num == 0) then
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.no_udp"))
|
||||
else
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.num_udp", {num = num}))
|
||||
end
|
||||
elseif (case == 2) then
|
||||
-- tcp
|
||||
if (num == 0) then
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.no_tcp"))
|
||||
else
|
||||
return(i18n("hosts_stats.page_scan_hosts.email.num_tcp", {num = num}))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to send notification after periodicity scan
|
||||
function vs_utils.notify_end_periodicity()
|
||||
-- @param is periodic (true -> is a periodic scan message, false -> is an all scan message)
|
||||
-- @param periodicity (can be nil in case of scan all)
|
||||
function vs_utils.notify_end_periodicity_or_all_scan(is_periodic, periodicity)
|
||||
|
||||
local notification_message = ""
|
||||
|
||||
local cve_num_redis_key, udp_ports_redis_key, tcp_ports_redis_key = get_counter_periodic_all_scan_keys(is_periodic)
|
||||
|
||||
|
||||
local cve_num_string = ntop.getCache(cve_num_redis_key)
|
||||
local cve_num = tonumber(cve_num_string) or 0
|
||||
|
||||
local udp_ports_string = ntop.getCache(udp_ports_redis_key)
|
||||
local udp_ports = tonumber(udp_ports_string) or 0
|
||||
|
||||
local tcp_ports_string = ntop.getCache(tcp_ports_redis_key)
|
||||
local tcp_ports = tonumber(tcp_ports_string) or 0
|
||||
|
||||
local title = i18n("hosts_stats.page_scan_hosts.email.vulnerability_scan_report_title",{host = getHttpHost()})
|
||||
|
||||
if (periodicity and periodicity == "1day") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.email.periodicity_scan_1_day_ended", {
|
||||
cves = format_num_for_email(cve_num,0),
|
||||
udp_ports = format_num_for_email(udp_ports,1),
|
||||
tcp_ports = format_num_for_email(tcp_ports,2),
|
||||
url = getHttpHost() .. ntop.getHttpPrefix() .. "/lua/pro/reportng.lua?report_template=vs_result"
|
||||
})
|
||||
|
||||
|
||||
elseif (periodicity and periodicity == "1week") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.email.periodicity_scan_1_week_ended", {
|
||||
cves = format_num_for_email(cve_num,0),
|
||||
udp_ports = format_num_for_email(udp_ports,1),
|
||||
tcp_ports = format_num_for_email(tcp_ports,2),
|
||||
url = getHttpHost() .. ntop.getHttpPrefix() .. "/lua/pro/reportng.lua?report_template=vs_result"
|
||||
})
|
||||
else
|
||||
-- scan all case
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.email.scan_all_ended", {
|
||||
cves = format_num_for_email(cve_num,0),
|
||||
udp_ports = format_num_for_email(udp_ports,1),
|
||||
tcp_ports = format_num_for_email(tcp_ports,2),
|
||||
url = getHttpHost() .. ntop.getHttpPrefix() .. "/lua/pro/reportng.lua?report_template=vs_result"
|
||||
})
|
||||
end
|
||||
|
||||
|
||||
|
||||
recipients.sendMessageByNotificationType({periodicity = periodicity, success=true, message = notification_message, title = title}, "vulnerability_scans")
|
||||
|
||||
ntop.setCache(cve_num_redis_key,"0")
|
||||
ntop.setCache(udp_ports_redis_key,"0")
|
||||
ntop.setCache(tcp_ports_redis_key,"0")
|
||||
|
||||
|
||||
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to verify if periodic scan is ended
|
||||
function vs_utils.is_periodic_scan_over()
|
||||
|
||||
local periodicity_scan_in_progress = ntop.getCache(host_to_scan_periodicity_key) == "1"
|
||||
|
||||
if (periodicity_scan_in_progress) then
|
||||
local hosts_details = vs_utils.retrieve_hosts_to_scan()
|
||||
for _,item in ipairs(hosts_details) do
|
||||
if(item.is_periodicity and item.is_ok_last_scan == vs_utils.scan_status.scheduled) then
|
||||
return
|
||||
|
||||
-- verify status of in progress periodic scanning
|
||||
if(item.is_periodicity and (item.is_ok_last_scan == vs_utils.scan_status.scheduled or item.is_ok_last_scan == vs_utils.scan_status.scanning)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -858,7 +1032,6 @@ function vs_utils.notify_end_periodicity()
|
|||
|
||||
local periodicity = ntop.getCache(host_to_scan_periodicity_key.."type")
|
||||
|
||||
|
||||
for _,item in ipairs(hosts_details) do
|
||||
local host_hash_key = vs_utils.get_host_hash_key(item.host, item.scan_type)
|
||||
local host_hash_value_string = ntop.getHashCache(host_to_scan_key, host_hash_key)
|
||||
|
|
@ -872,15 +1045,58 @@ function vs_utils.notify_end_periodicity()
|
|||
end
|
||||
end
|
||||
|
||||
local notification_message = ""
|
||||
if (periodicity == "1day") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.periodicity_scan_1_day_ended")
|
||||
elseif (periodicity == "1week") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.periodicity_scan_1_week_ended")
|
||||
end
|
||||
recipients.sendMessageByNotificationType({periodicity = periodicity, success=true, message = notification_message}, "vulnerability_scans")
|
||||
return true, periodicity
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to verify if scan all is ended
|
||||
function vs_utils.is_scan_all_over()
|
||||
|
||||
local scan_all_in_progress = ntop.getCache(host_to_scan_all_key) == "1"
|
||||
|
||||
if (scan_all_in_progress) then
|
||||
local hosts_details = vs_utils.retrieve_hosts_to_scan()
|
||||
for _,item in ipairs(hosts_details) do
|
||||
|
||||
-- verify status of in progress periodic scanning
|
||||
if(item.is_all and (item.is_ok_last_scan == vs_utils.scan_status.scheduled or item.is_ok_last_scan == vs_utils.scan_status.scanning)) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
ntop.setCache(host_to_scan_all_key, "0")
|
||||
|
||||
|
||||
for _,item in ipairs(hosts_details) do
|
||||
local host_hash_key = vs_utils.get_host_hash_key(item.host, item.scan_type)
|
||||
local host_hash_value_string = ntop.getHashCache(host_to_scan_key, host_hash_key)
|
||||
if(not isEmptyString(host_hash_value_string)) then
|
||||
|
||||
local host_hash_value = json.decode(host_hash_value_string)
|
||||
|
||||
host_hash_value.is_all = false
|
||||
|
||||
ntop.setHashCache(host_to_scan_key, host_hash_key, json.encode(host_hash_value))
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
||||
-- Function to enable periodic scan end check on callbacks
|
||||
function vs_utils.is_periodic_scan_running()
|
||||
return ntop.getCache(host_to_scan_periodicity_key) == "1"
|
||||
end
|
||||
|
||||
-- **********************************************************
|
||||
|
|
@ -1110,7 +1326,7 @@ function vs_utils.scan_host(scan_type, host, ports, scan_id, use_coroutines)
|
|||
end
|
||||
end
|
||||
|
||||
vs_utils.set_status_scan(scan_type, host, ports_scan_param, id, nil, vs_utils.scan_status.scanning)
|
||||
vs_utils.set_status_scan(scan_type, host, ports_scan_param, id, nil,nil, vs_utils.scan_status.scanning)
|
||||
|
||||
-- Save on redis the scanning host to avoid inconsistent state on ntopng restarts
|
||||
local scanning_host = {scan_type = scan_type, host = host, ports = ports_scan_param, id = scan_id}
|
||||
|
|
@ -1146,7 +1362,7 @@ end
|
|||
-- **********************************************************
|
||||
|
||||
-- Function to update single host status
|
||||
function vs_utils.set_status_scan(scan_type, host, ports, id, is_periodicity, status)
|
||||
function vs_utils.set_status_scan(scan_type, host, ports, id, is_periodicity, is_all, status)
|
||||
|
||||
local host_hash_key = vs_utils.get_host_hash_key(host, scan_type)
|
||||
local host_hash_value_string = ntop.getHashCache(host_to_scan_key, host_hash_key)
|
||||
|
|
@ -1159,6 +1375,10 @@ function vs_utils.set_status_scan(scan_type, host, ports, id, is_periodicity, st
|
|||
host_hash_value.is_periodicity = is_periodicity
|
||||
end
|
||||
|
||||
if (is_all ~= nil) then
|
||||
host_hash_value.is_all = is_all
|
||||
end
|
||||
|
||||
ntop.setHashCache(host_to_scan_key, host_hash_key, json.encode(host_hash_value))
|
||||
end
|
||||
|
||||
|
|
@ -1167,9 +1387,9 @@ end
|
|||
|
||||
-- **********************************************************
|
||||
|
||||
function vs_utils.schedule_host_scan(scan_type, host, ports, scan_id, is_periodicity)
|
||||
function vs_utils.schedule_host_scan(scan_type, host, ports, scan_id, is_periodicity, is_all)
|
||||
local scan = { scan_type = scan_type, host = host, ports = ports, id= scan_id}
|
||||
vs_utils.set_status_scan(scan_type, host, ports, scan_id, is_periodicity, vs_utils.scan_status.scheduled)
|
||||
vs_utils.set_status_scan(scan_type, host, ports, scan_id, is_periodicity, is_all, vs_utils.scan_status.scheduled)
|
||||
|
||||
ntop.rpushCache(host_scan_queue_key, json.encode(scan))
|
||||
|
||||
|
|
@ -1180,13 +1400,23 @@ end
|
|||
|
||||
function vs_utils.schedule_all_hosts_scan()
|
||||
local host_to_scan_list = vs_utils.retrieve_hosts_to_scan()
|
||||
|
||||
|
||||
local is_scanning_almost_one = false
|
||||
if #host_to_scan_list > 0 then
|
||||
for _,scan_info in ipairs(host_to_scan_list) do
|
||||
vs_utils.schedule_host_scan(scan_info.scan_type, scan_info.host, scan_info.ports, scan_info.id, false)
|
||||
vs_utils.schedule_host_scan(scan_info.scan_type, scan_info.host, scan_info.ports, scan_info.id, false, true)
|
||||
is_scanning_almost_one = true
|
||||
end
|
||||
end
|
||||
|
||||
if (is_scanning_almost_one) then
|
||||
ntop.setCache(host_to_scan_all_key , "1")
|
||||
end
|
||||
|
||||
ntop.setCache(host_scan_all_cve_num_key,"0")
|
||||
ntop.setCache(host_scan_all_udp_ports_key,"0")
|
||||
ntop.setCache(host_scan_all_tcp_ports_key,"0")
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
|
@ -1207,7 +1437,7 @@ function vs_utils.schedule_periodic_scan(periodicity)
|
|||
local frequency = scan_info.scan_frequency
|
||||
|
||||
if(frequency == periodicity) then
|
||||
vs_utils.schedule_host_scan(scan_info.scan_type, scan_info.host, scan_info.ports, scan_info.id, true)
|
||||
vs_utils.schedule_host_scan(scan_info.scan_type, scan_info.host, scan_info.ports, scan_info.id, true, false)
|
||||
is_scanning_almost_one = true
|
||||
end
|
||||
end
|
||||
|
|
@ -1217,14 +1447,11 @@ function vs_utils.schedule_periodic_scan(periodicity)
|
|||
ntop.setCache(host_to_scan_periodicity_key , "1")
|
||||
ntop.setCache(host_to_scan_periodicity_key.."type", periodicity)
|
||||
|
||||
local notification_message = ""
|
||||
if (periodicity == "1day") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.periodicity_scan_1_day_started")
|
||||
elseif (periodicity == "1week") then
|
||||
notification_message = i18n("hosts_stats.page_scan_hosts.periodicity_scan_1_week_started")
|
||||
end
|
||||
|
||||
ntop.setCache(host_periodic_scan_cve_num_key , "0")
|
||||
ntop.setCache(host_periodic_scan_udp_ports_key , "0")
|
||||
ntop.setCache(host_periodic_scan_tcp_ports_key , "0")
|
||||
|
||||
recipients.sendMessageByNotificationType({periodicity = periodicity, success=true, message = notification_message}, "vulnerability_scans")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue