This commit is contained in:
Luca Deri 2023-12-01 12:26:51 +01:00
parent 24ff8799bc
commit 227f4493ee

View file

@ -285,7 +285,7 @@ end
-- ##############################################
local function save_last_result(scan_result, scan_type, host, epoch, last_port_scanned_label)
if(scan_result ~= nil and not ntop.isClickHouseEnabled()) then
local handle = io.open(get_report_path(scan_type, host), "a")
local result = handle:write("\n\n"..i18n("hosts_stats.page_scan_hosts.inconsistency_state", {port = last_port_scanned_label}).."\n"..scan_result)
@ -303,14 +303,10 @@ end
local function verify_status_ports(possible_changed_ports, host, scan_type, open_ports_case, epoch)
local real_ports = {}
local scan_module = vs_utils.load_module(scan_type)
if (test_me) then
tprint("TROVATA inconsistent")
ntop.msleep(10000)
tprint("RESCANNING")
end
for _,possible_changed_port in ipairs(possible_changed_ports) do
local now,result,duration,scan_result,num_open_ports,num_vulnerabilities_found, cve, udp_ports, tcp_ports = scan_module:scan_host(host, possible_changed_port)
local scan_type_label = ternary(scan_type == "tcp_portscan", "tcp", "udp")
local port_label_for_vs_result = string.format("%u/%s",possible_changed_port,scan_type_label)
save_last_result(result, scan_type, host, epoch, port_label_for_vs_result)
@ -363,7 +359,7 @@ local function analyze_ports_diff(ports_difference, host, scan_type, epoch)
rsp["ports_case"] = ports_difference.case
if ((real_closed_ports_num == ports_difference.closed_ports_num) and (real_open_port_num == ports_difference.open_ports_num)) then
-- case ok we can trigger alert
else
-- false positive detected
@ -409,7 +405,7 @@ local function get_ports_changes(host, scan_type, old_data, new_data)
end
local ports_differences = check_ports_diffences(#old_ports, old_ports,
#new_ports, new_ports)
#new_ports, new_ports)
local rsp_diff = analyze_ports_diff(ports_differences, host, scan_type, new_data.last_scan_time)
if (rsp_diff.triggered) then
rsp["open_ports"] = rsp_diff.open_ports
@ -442,12 +438,12 @@ local function check_differences(host, host_name, scan_type, old_data, new_data)
end
--[[
if tonumber(old_data.ports or 0) ~= tonumber(new_data.ports or 0) then
if tonumber(old_data.ports or 0) ~= tonumber(new_data.ports or 0) then
rsp["num_ports"] = {
old_num_ports = old_data.ports or 0,
new_num_ports = new_data.ports or 0
old_num_ports = old_data.ports or 0,
new_num_ports = new_data.ports or 0
}
end
end
--]]
local num_cve_solved = 0
local num_new_cve_issues = 0
@ -594,7 +590,7 @@ function vs_utils.cleanup_nmap_result(scan_result, scan_type)
local url = cve_utils.getDocURL(c[1], scan_type)
if(scan_type == "cve") then
l = '[<A HREF="'..url..'">'..c[1]..'</A>]'..c[2]
l = '[<A HREF="'..url..'">'..c[1]..'</A>]'..c[2]
elseif(scan_type == "openvas") then
l = '[<A HREF="'..url..'">'..c[1]..'</A>]'..c[2]
end
@ -628,7 +624,7 @@ function vs_utils.cleanup_nmap_check_host_result(scan_result)
table.remove(scan_result, 1)
table.remove(scan_result, #scan_result)
local is_up_and_run = false
local is_up_and_run = false
for _,l in pairs(scan_result) do
-- searching for "Host is up" nmap string
if (string.find(l, "Host is up") ~= nil) then
@ -786,10 +782,12 @@ local function get_counter_periodic_all_scan_keys(exec_type)
end
-- **********************************************************
local function get_host_id(host_details)
local host_id = ternary(isEmptyString(host_details.host_name),host_details.host, string.format("%s (%s)",host_details.host_name,host_details.host))
return host_id
end
-- **********************************************************
-- Function to update counters of periodically scan or scan all
@ -797,9 +795,9 @@ end
local function update_scan_info_for_report(type_of_scan_execution, new_item, host_hash_key, discrepancies, is_down)
-- select correctly redis keys
local redis_info_key = get_counter_periodic_all_scan_keys(type_of_scan_execution)
local info_string = ntop.getCache(redis_info_key)
local info_json = nil
if (info_string ~= nil) then
info_json = json.decode(info_string)
end
@ -811,26 +809,23 @@ local function update_scan_info_for_report(type_of_scan_execution, new_item, hos
local host_id = get_host_id(new_item)
-- handle hosts down list for email
if (is_down) then
info_json.down_hosts = true
local host_down = i18n("hosts_stats.page_scan_hosts.email.host_down_item", {
host_id = host_id
})
info_json.hosts_down = true
local host_down = i18n("hosts_stats.page_scan_hosts.email.host_down_item", { host_id = host_id })
if (info_json and isEmptyString(info_json.down_hosts_string_list)) then
info_json.down_hosts_string_list = host_down
else
info_json.down_hosts_string_list = info_json.down_hosts_string_list .. host_down
if (info_json) then
if(info_json.hosts_down_list == nil) then
info_json.hosts_down_list = {}
end
info_json.hosts_down_list[host_down] = true
info_json.not_scanned_hosts = table.len(info_json.hosts_down_list)
end
if (info_json and info_json.not_scanned_hosts ~= nil) then
-- count just in success case
info_json.not_scanned_hosts = tonumber(info_json.not_scanned_hosts) + 1
else
info_json.not_scanned_hosts = 1
end
goto continue
end
-- **********************************************************
if (new_item.num_vulnerabilities_found ~= nil) then
if (info_json ~= {} and info_json.cves ~= nil) then
@ -860,14 +855,13 @@ local function update_scan_info_for_report(type_of_scan_execution, new_item, hos
if (new_item.is_ok_last_scan == vs_utils.scan_status.ok) then
if (info_json ~= {} and info_json.scanned_hosts ~= nil) then
-- count just in success case
info_json.scanned_hosts = tonumber(info_json.scanned_hosts) + 1
-- count just in success case
info_json.scanned_hosts = tonumber(info_json.scanned_hosts) + 1
else
info_json.scanned_hosts = 1
end
end
end
if (info_json ~= {} and info_json.begin_epoch == nil) then
info_json.begin_epoch = os.time()
end
@ -888,7 +882,7 @@ local function update_scan_info_for_report(type_of_scan_execution, new_item, hos
prefix_key = "udp_"
end
if (not cve_case and info_json ~= {}) then
-- DISCREPANCY PORTS CASES
info_json.discrepancy_case = 'ports'
@ -897,11 +891,11 @@ local function update_scan_info_for_report(type_of_scan_execution, new_item, hos
-- take only open ports not the closed ports
info_json.new_open_ports = tonumber(info_json.new_open_ports or 0) + tonumber(discrepancies[prefix_key.."open_ports"].num or 0)
host_discrepancies_details = i18n("hosts_stats.page_scan_hosts.email.host_port_discrepancy_description", {
host_id = host_id,
port_type = port_type,
ports = discrepancies[prefix_key.."open_ports"].ports
host_id = host_id,
port_type = port_type,
ports = discrepancies[prefix_key.."open_ports"].ports
})
if (isEmptyString(info_json.hosts_discrepancies_details)) then
info_json.hosts_discrepancies_details = host_discrepancies_details
else
@ -916,8 +910,8 @@ local function update_scan_info_for_report(type_of_scan_execution, new_item, hos
local cve_string = format_port_list_to_string(discrepancies.cve_solved)
host_discrepancies_details = i18n("hosts_stats.page_scan_hosts.email.host_cve_discrepancy_description", {
host_id = host_id,
cves = cve_string,
host_id = host_id,
cves = cve_string,
})
if (isEmptyString(info_json.hosts_discrepancies_details)) then
@ -1089,7 +1083,7 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
-- In case the alert needs to be triggered, save the differences in order to lessen
-- the info dropped on redis
-- if is_ok_last_scan is nil then no prior scan was done, so do not trigger the alert
local epoch_id = 0
if isEmptyString(id) then
@ -1108,7 +1102,7 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
-- case host is not up and running, possible just in TCP/UDP portscan
trigger_alert_host_down(host,host_name,last_scan_time)
is_down = true
end
@ -1194,7 +1188,7 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
-- add ports statistics comparing the ntopng passive monitoring info
if (scan_type == "tcp_portscan" or scan_type == "tcp_openports" or scan_type == "udp_portscan") then
local compare_info = vs_rest_utils.compare_scan_info_ntopng_info(host, scan_type, new_item.tcp_ports_list, new_item.udp_ports_list)
new_item.host_in_mem = compare_info.host_in_mem
local prefix_key = "udp_"
if (scan_type == "tcp_portscan" or scan_type == "tcp_openports") then
@ -1211,7 +1205,7 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
local counts = vs_utils.update_ts_counters()
-- save on db here
@ -1219,21 +1213,21 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
local hash_prefs_string = ntop.getHashCache(prefs_host_values_key,host_hash_key)
-- hash value found
local hash_pref_value = json.decode(hash_prefs_string)
if (hash_pref_value ~= nil) then
if (hash_pref_value ~= nil) then
-- is necessary this check to avoid to save entries not presents in the config and to save all data of the entry.
for key,value in pairs(hash_pref_value) do
if (key ~= 'is_ok_last_scan') then
new_item[key] = value
end
end
vs_db_utils.save_vs_result(scan_type, host, new_item.last_scan.epoch, json.encode(new_item), scan_result)
end
local host_info_differences
if trigger_alert and old_data and (not is_edit) and
if trigger_alert and old_data and (not is_edit) and
-- old scan and new scan must be successfully to perform discrepancies check
(old_data.is_ok_last_scan == vs_utils.scan_status.ok and new_item.is_ok_last_scan == vs_utils.scan_status.ok)
(old_data.is_ok_last_scan == vs_utils.scan_status.ok and new_item.is_ok_last_scan == vs_utils.scan_status.ok)
then
local already_scanned = (old_data.last_scan and old_data.last_scan.epoch)
@ -1266,7 +1260,7 @@ function vs_utils.save_host_to_scan(scan_type, host, scan_result, last_scan_time
udp_ports = udp_ports,
last_scan_time = last_scan_time
})
})
if host_info_to_cache then
host_info_differences = host_info_to_cache
@ -1383,7 +1377,7 @@ end
-- **********************************************************
local function retrieve_email_info(exec_type)
local function retrieve_email_info(exec_type)
local info_redis_key = get_counter_periodic_all_scan_keys(exec_type)
local info_string = ntop.getCache(info_redis_key)
@ -1414,69 +1408,33 @@ local function retrieve_email_info(exec_type)
report_type = exec_type,
-- has_dicrepancy must be true only if there are new open ports or cves fixed
has_discrepancy = ((info_json.new_open_ports or 0) > 0) or ((info_json.num_cve_solved or 0) > 0),
down_hosts = info_json.down_hosts
}
hosts_down = info_json.hosts_down_list
}
if (email_info.has_discrepancy) then
email_info.new_open_ports = info_json.new_open_ports or 0
email_info.fixed_cves = info_json.num_cve_solved or 0
email_info.discrepancies_details = tostring(info_json.hosts_discrepancies_details)
end
if (email_info.down_hosts) then
email_info.down_hosts_string_list = tostring(info_json.down_hosts_string_list)
end
email_info.duration = email_info.end_epoch_t - email_info.begin_epoch_t
ntop.setCache(info_redis_key,json.encode({
cves = 0,
udp_ports = 0,
tcp_ports = 0,
begin_epoch = 0,
scanned_hosts = 0,
not_scanned_hosts = 0
cves = 0,
udp_ports = 0,
tcp_ports = 0,
begin_epoch = 0,
scanned_hosts = 0,
not_scanned_hosts = 0
}))
return email_info
end
-- **********************************************************
-- Function to check if an host is already present into
-- the hosts list to save on db for report
local function is_already_present_host_in_no_duplicated_result(result_no_duplicated, host)
if (next(result_no_duplicated)) then
for _,item in ipairs(result_no_duplicated) do
if (item.host == host) then
return true
end
end
end
return false
end
-- **********************************************************
-- Function to remove duplicated of down hosts
local function remove_duplicated_host_down(host_scanned_info)
local result_no_duplicated = {}
for _,item in ipairs(host_scanned_info) do
if (item.is_down) then
if (not is_already_present_host_in_no_duplicated_result(result_no_duplicated, item.host)) then
result_no_duplicated[#result_no_duplicated+1] = item
end
else
result_no_duplicated[#result_no_duplicated+1] = item
end
end
return result_no_duplicated
end
-- **********************************************************
-- Function to retrieves report info
local function retrieve_report_info(date)
local host_scanned_info = vs_utils.retrieve_hosts_to_scan()
local info = {
cves = 0,
tcp_ports = 0,
@ -1484,6 +1442,7 @@ local function retrieve_report_info(date)
scanned_hosts = 0,
not_scanned_hosts = 0
}
for _, item in ipairs(host_scanned_info) do
if (not isEmptyString(item.num_vulnerabilities_found)) then
info.cves = info.cves + tonumber(item.num_vulnerabilities_found)
@ -1508,8 +1467,6 @@ local function retrieve_report_info(date)
local info_date_formatted = tostring(formatEpoch(info.date))
info.name = "Report of "..info_date_formatted
info.all_data_details = remove_duplicated_host_down(host_scanned_info)
return info
end
-- **********************************************************
@ -1518,35 +1475,35 @@ end
function vs_utils.generate_report(date)
local report_info = retrieve_report_info(date)
vs_db_utils.save_report_info(report_info)
return report_info
end
local function add_ports_open_for_email_report(l4_key_prefix, host_details)
if (tonumber(host_details[l4_key_prefix.."_ports"]) > 0) then
return (i18n("hosts_stats.page_scan_hosts.email.host_details_open_ports", {
ports_list = host_details[l4_key_prefix.."_ports_list"],
l4_proto = ternary(l4_key_prefix == "tcp", "TCP", "UDP")
ports_list = host_details[l4_key_prefix.."_ports_list"],
l4_proto = ternary(l4_key_prefix == "tcp", "TCP", "UDP")
}))
end
return nil
end
local function format_all_hosts_details_info_for_email(all_hosts_details)
local function format_all_hosts_details_info_for_email(all_hosts_details)
local formatted_hosts_details_string = ""
for _,host_details in ipairs(all_hosts_details) do
-- by default the first element is the scan type always fullfil
local label_id_scan_type = string.format("hosts_stats.page_scan_hosts.scan_type_list.%s",host_details.scan_type)
local scan_type_label = i18n(label_id_scan_type)
local formatted_host_details_string = i18n("hosts_stats.page_scan_hosts.email.host_details_scan_type",{
scan_type = scan_type_label
scan_type = scan_type_label
})
local host_id = get_host_id(host_details)
local tcp_prefix = "tcp"
local udp_prefix = "udp"
@ -1566,8 +1523,8 @@ local function format_all_hosts_details_info_for_email(all_hosts_details)
end
local host_details_email_line = i18n("hosts_stats.page_scan_hosts.email.host_details", {
host_id = host_id,
details = formatted_host_details_string
host_id = host_id,
details = formatted_host_details_string
})
formatted_hosts_details_string = formatted_hosts_details_string .. host_details_email_line
@ -1585,13 +1542,13 @@ end
function vs_utils.notify_scan_results(exec_type, periodicity)
local notification_message = ""
local email_info = retrieve_email_info(exec_type)
local email_info = retrieve_email_info(exec_type)
local title = i18n("hosts_stats.page_scan_hosts.email.vulnerability_scan_report_title",{host = getHttpHost()})
local duration = 0
local duration_label = ''
if (email_info.duration ~= nil) then
duration_label = secondsToTime(email_info.duration)
end
@ -1616,57 +1573,62 @@ function vs_utils.notify_scan_results(exec_type, periodicity)
end
local skipped_hosts_list = ""
local no_down_hosts_br = ""
if (email_info.down_hosts) then
skipped_hosts_list = i18n("hosts_stats.page_scan_hosts.email.host_down_list", {
host_down_items = email_info.down_hosts_string_list
})
else
no_down_hosts_br = "</br><br>"
local no_hosts_down_br = ""
if (email_info.hosts_down) then
local ret = ""
for k, v in pairsByKeys(email_info.hosts_down, asc) do
ret = ret .. k .. "\n"
end
skipped_hosts_list = i18n("hosts_stats.page_scan_hosts.email.host_down_list", { host_down_items = ret })
else
no_hosts_down_br = "</br><br>"
end
notification_message = i18n(email_body_i18n_key, {
cves = format_num_for_email(email_info.cve_num,0),
udp_ports = format_num_for_email(email_info.udp_ports,1),
tcp_ports = format_num_for_email(email_info.tcp_ports,2),
scanned_hosts = format_num_for_email(email_info.scanned_hosts, 3),
not_scanned_hosts = format_num_for_email(email_info.not_scanned_hosts, 4),
no_down_hosts_br = no_down_hosts_br,
skipped_hosts_list = skipped_hosts_list,
duration = duration_label,
start_date = start_date_formatted,
end_date = end_date_formatted,
})
cves = format_num_for_email(email_info.cve_num,0),
udp_ports = format_num_for_email(email_info.udp_ports,1),
tcp_ports = format_num_for_email(email_info.tcp_ports,2),
scanned_hosts = format_num_for_email(email_info.scanned_hosts, 3),
not_scanned_hosts = format_num_for_email(email_info.not_scanned_hosts, 4),
no_hosts_down_br = no_hosts_down_br,
skipped_hosts_list = skipped_hosts_list,
duration = duration_label,
start_date = start_date_formatted,
end_date = end_date_formatted,
})
local possible_discrepancies_info = ""
local add_br = ""
if (email_info.has_discrepancy) then
possible_discrepancies_info = i18n("hosts_stats.page_scan_hosts.email.discrepancy", {
new_ports_open = ternary(email_info.new_open_ports ~= 0, format_high_num_value_for_tables({num = email_info.new_open_ports}, "num"),"0"),
cves_fixed = ternary(email_info.fixed_cves ~= 0, format_high_num_value_for_tables({num = email_info.fixed_cves }, "num"),"0"),
hosts_discrepancy_details = email_info.discrepancies_details
new_ports_open = ternary(email_info.new_open_ports ~= 0, format_high_num_value_for_tables({num = email_info.new_open_ports}, "num"),"0"),
cves_fixed = ternary(email_info.fixed_cves ~= 0, format_high_num_value_for_tables({num = email_info.fixed_cves }, "num"),"0"),
hosts_discrepancy_details = email_info.discrepancies_details
})
else
else
add_br = "<br>"
possible_discrepancies_info = i18n("hosts_stats.page_scan_hosts.email.no_discrepancy")
end
notification_message = notification_message .. possible_discrepancies_info
local report_link_line = i18n("hosts_stats.page_scan_hosts.email.report_link_line",{url = string.format(getHttpHost() .. ntop.getHttpPrefix() .. "/lua/enterprise/vulnerability_scan_report.lua?epoch_end=%u&epoch_begin=%u",report_date,report_date), add_br = add_br})
local report_link_line = i18n("hosts_stats.page_scan_hosts.email.report_link_line",
{url = string.format(getHttpHost() .. ntop.getHttpPrefix() .. "/lua/enterprise/vulnerability_scan_report.lua?epoch_end=%u&epoch_begin=%u",
report_date,report_date), add_br = add_br})
notification_message = notification_message .. report_link_line
vs_utils.generate_report(email_info.end_epoch_t)
--local hosts_details = format_all_hosts_details_info_for_email(report_info.all_data_details)
--notification_message = string.format("%s<br><br>%s",notification_message,hosts_details)
if verbose then
traceError(TRACE_NORMAL,TRACE_CONSOLE, "Vulnerability Scan completed. Sending " .. title .."\n")
end
recipients.sendMessageByNotificationType({periodicity = periodicity, success = true, message = notification_message, title = title}, "vulnerability_scans")
end
-- **********************************************************
@ -1796,7 +1758,7 @@ end
-- **********************************************************
local function retrieve_host_by_hash_key(host_hash_key)
local function retrieve_host_by_hash_key(host_hash_key)
local hash_value_string = ntop.getHashCache(host_to_scan_key, host_hash_key)
local hash_prefs_string = ntop.getHashCache(prefs_host_values_key,host_hash_key)
local hash_value = json.decode(hash_prefs_string)
@ -1846,11 +1808,11 @@ function vs_utils.retrieve_hosts_to_scan(epoch)
hash_value = json.decode(hash_value_string)
local hash_pref_value = json.decode(hash_prefs_string) or {}
for key,value in pairs(hash_pref_value) do
if (key ~= 'is_ok_last_scan') then
hash_value[key] = value
end
end
for key,value in pairs(hash_pref_value) do
if (key ~= 'is_ok_last_scan') then
hash_value[key] = value
end
end
else
-- hash value not found
ntop.setHashCache(host_to_scan_key, k, hash_prefs_string)
@ -1898,7 +1860,7 @@ end
-- Function restrieve scan result from FS
local function retrieve_scan_result_from_file(scan_type, host)
-- for retrocompatibility
-- for retrocompatibility
local path = get_report_path(scan_type, host)
if(ntop.exists(path)) then
@ -1910,19 +1872,19 @@ local function retrieve_scan_result_from_file(scan_type, host)
else
return("Unable to read file "..path)
end
end
-- **********************************************************
-- Function to retrieve last host scan result
function vs_utils.retrieve_hosts_scan_result(scan_type, host, epoch)
-- retrieve from DB
local db_result
local fs_result
local is_clickhouse_enabled = ntop.isClickHouseEnabled()
-- retrieve data here
if (is_clickhouse_enabled) then
-- retrieve from DB
@ -1940,7 +1902,7 @@ function vs_utils.retrieve_hosts_scan_result(scan_type, host, epoch)
-- ****************************************
-- retrocompatibility case:
-- when there were results saved on FS,
-- when there were results saved on FS,
-- but the user updates ntopng to use clickhouse,
-- and there are currently no results in clickhouse.
-- ****************************************
@ -2156,15 +2118,15 @@ end
-- **********************************************************
local function set_single_scan_in_progress()
if (ntop.getCache(single_scan_key) ~= '1') then
if (ntop.getCache(single_scan_key) ~= '1') then
ntop.setCache(single_scan_key, "1")
ntop.setCache(single_scan_info_key, json.encode({
cves = 0,
udp_ports = 0,
tcp_ports = 0,
begin_epoch = os.time(),
scanned_host = 1
cves = 0,
udp_ports = 0,
tcp_ports = 0,
begin_epoch = os.time(),
scanned_host = 1
}))
end
@ -2206,7 +2168,7 @@ end
function vs_utils.schedule_ondemand_single_host_scan(scan_type, host, ports, scan_id, is_periodicity, is_all, is_single_scan)
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, is_all, is_single_scan, vs_utils.scan_status.scheduled)
ntop.rpushCache(host_scan_queue_key, json.encode(scan))
@ -2530,12 +2492,12 @@ end
function vs_utils.nmap_check_host(host_ip, use_coroutines)
local nmap = vs_utils.get_nmap_path()
local scan_command = nmap.." -sn"
local scan_command = nmap.." -sn"
-- IPv6 check (need to use --privileged otherwise nmap will report hosts are down even if up)
if(string.contains(host_ip, ':')) then scan_command = scan_command .. " --privileged -6" end
scan_command = string.format("%s %s",scan_command,host_ip)
if(debug_me) then traceError(TRACE_NORMAL, TRACE_CONSOLE, "Executing: "..scan_command.."\n") end
local start_scan = os.time()
@ -2546,7 +2508,7 @@ function vs_utils.nmap_check_host(host_ip, use_coroutines)
local is_up = vs_utils.cleanup_nmap_check_host_result(result)
if(debug_me) then traceError(TRACE_NORMAL, TRACE_CONSOLE, "Host is up: "..tostring(is_up).."\n") end
return is_up, scan_duration, start_scan, end_scan
return is_up, scan_duration, start_scan, end_scan
end
-- **********************************************************
@ -2615,7 +2577,7 @@ end
-- **********************************************************
-- Function to trigger an alert if the host
-- is not configured
-- is not configured
function vs_utils.triggerHostNotConfiguredAlert(host)
trigger_alert_host_not_configured(host)
@ -2624,7 +2586,7 @@ end
-- **********************************************************
-- ##########################################################
-- VS DB Functions
-- VS DB Functions
-- **********************************************************
function vs_utils.retrieve_report_list(epoch)
@ -2651,4 +2613,5 @@ function vs_utils.edit_report(epoch, report_name)
end
-- ##########################################################
return vs_utils