ntopng/scripts/lua/admin/prefs.lua
emanuele-f 20ef1a4ebc Fix ts_utils.listSeries in redis.lua being performed on every page load
This was caused by probe.getTimeseriesMenu being called at every page load by the timeseries
code to load the schemas. probe.loadSchemas is now called instead.
2019-11-25 15:39:21 +01:00

1877 lines
79 KiB
Lua

--
-- (C) 2013-18 - ntop.org
--
local dirs = ntop.getDirs()
package.path = dirs.installdir .. "/scripts/lua/modules/?.lua;" .. package.path
package.path = dirs.installdir .. "/scripts/lua/modules/timeseries/drivers/?.lua;" .. package.path -- for influxdb
if((dirs.scriptdir ~= nil) and (dirs.scriptdir ~= "")) then package.path = dirs.scriptdir .. "/lua/modules/?.lua;" .. package.path end
require "lua_utils"
require "prefs_utils"
require "alert_utils"
local template = require "template_utils"
local callback_utils = require "callback_utils"
local lists_utils = require "lists_utils"
local telemetry_utils = require "telemetry_utils"
local alert_consts = require "alert_consts"
local slack_utils = require("slack")
local webhook_utils = require("webhook")
local recording_utils = require "recording_utils"
local remote_assistance = require "remote_assistance"
local data_retention_utils = require "data_retention_utils"
local page_utils = require("page_utils")
local ts_utils = require("ts_utils")
local influxdb = require("influxdb")
local alert_endpoints = require("alert_endpoints_utils")
local nindex_utils = nil
local info = ntop.getInfo()
local email_peer_pattern = [[^(([A-Za-z0-9._%+-]|\s)+<)?[A-Za-z0-9._%+-]+@[a-z0-9.-]+\.[a-z]{2,6}>?$]]
if(ntop.isPro()) then
package.path = dirs.installdir .. "/scripts/lua/pro/?.lua;" .. package.path
package.path = dirs.installdir .. "/scripts/lua/pro/modules/?.lua;" .. package.path
if hasNindexSupport() then
nindex_utils = require("nindex_utils")
end
end
sendHTTPContentTypeHeader('text/html')
local show_advanced_prefs = false
local alerts_disabled = false
local product = ntop.getInfo().product
local message_info = ""
local message_severity = "alert-warning"
-- NOTE: all the auth methods should be listed below
local auth_toggles = {
["local"] = "toggle_local_auth",
["ldap"] = "toggle_ldap_auth",
["http"] = "toggle_http_auth",
["radius"] = "toggle_radius_auth",
}
if(haveAdminPrivileges()) then
if not table.empty(_POST) then
if _GET["tab"] == "auth" then
local one_enabled = false
for k, v in pairs(auth_toggles) do
if _POST[v] == "1" then
one_enabled = true
break
end
end
if not one_enabled then
-- at least one auth method should be enabled
_POST["toggle_local_auth"] = "1"
end
end
end
if(_POST["email_sender"] ~= nil) then
_POST["email_sender"] = unescapeHTML(_POST["email_sender"])
end
if(_POST["email_recipient"] ~= nil) then
_POST["email_recipient"] = unescapeHTML(_POST["email_recipient"])
end
if(_POST["flush_alerts_data"] ~= nil) then
require "alert_utils"
flushAlertsData()
elseif(_POST["disable_alerts_generation"] == "1") then
require "alert_utils"
disableAlertsGeneration()
elseif(_POST["send_test_email"] ~= nil) then
local email_utils = require("email")
local success = email_utils.sendEmail("TEST MAIL", "Email notification is working")
if success then
message_info = i18n("prefs.email_sent_successfully")
message_severity = "alert-success"
else
message_info = i18n("prefs.email_send_error", {url="https://www.ntop.org/guides/ntopng/web_gui/alerts.html#email"})
message_severity = "alert-danger"
end
elseif(_POST["send_test_slack"] ~= nil) then
local success = slack_utils.sendMessage("interface", "info", "Slack notification is working")
if success then
message_info = i18n("prefs.slack_sent_successfully", {channel=slack_utils.getChannelName("interface")})
message_severity = "alert-success"
else
message_info = i18n("prefs.slack_send_error", {product=product})
message_severity = "alert-danger"
end
elseif(_POST["send_test_webhook"] ~= nil) then
local success = webhook_utils.sendMessage({})
if success then
message_info = i18n("prefs.webhook_sent_successfully")
message_severity = "alert-success"
else
message_info = i18n("prefs.webhook_send_error", {product=product})
message_severity = "alert-danger"
end
elseif (_POST["timeseries_driver"] == "influxdb") then
local url = string.gsub(string.gsub( _POST["ts_post_data_url"], "http:__", "http://"), "https:__", "https://")
if ntop.getPref("ntopng.prefs.timeseries_driver") ~= "influxdb"
or (url ~= ntop.getPref("ntopng.prefs.ts_post_data_url"))
or (_POST["influx_dbname"] ~= ntop.getPref("ntopng.prefs.influx_dbname"))
or (_POST["influx_retention"] ~= ntop.getPref("ntopng.prefs.influx_retention"))
or (_POST["toggle_influx_auth"] ~= ntop.getPref("ntopng.prefs.influx_auth_enabled"))
or (_POST["influx_username"] ~= ntop.getPref("ntopng.prefs.influx_username"))
or (_POST["influx_password"] ~= ntop.getPref("ntopng.prefs.influx_password")) then
local username = nil
local password = nil
if _POST["toggle_influx_auth"] == "1" then
username = _POST["influx_username"]
password = _POST["influx_password"]
end
local ok, message = influxdb.init(_POST["influx_dbname"], url, tonumber(_POST["influx_retention"]),
username, password, false --[[verbose]])
if not ok then
-- NOTE: already logged
--~ message_info = message
--~ message_severity = "alert-danger"
-- reset driver to the old one
_POST["timeseries_driver"] = nil
elseif message then
message_info = message
message_severity = "alert-success"
end
end
elseif(_POST["n2disk_license"] ~= nil) then
recording_utils.setLicense(_POST["n2disk_license"])
end
if _POST["timeseries_driver"] ~= nil then
ts_utils.setupAgain()
end
local slack_channels_key = "ntopng.prefs.alerts.slack_channels"
for k, v in pairs(_POST) do
if starts(k, "slack_ch_") then
local alert_entity = tonumber(split(k, "slack_ch_")[2])
local alert_entity_raw = alert_consts.alertEntityRaw(alert_entity)
if alert_entity_raw then
-- map entity -> channel name
if alert_entity_raw == v then
ntop.delHashCache(slack_channels_key, alert_entity_raw)
else
ntop.setHashCache(slack_channels_key, alert_entity_raw, v)
end
end
end
end
page_utils.print_header(i18n("prefs.preferences"))
active_page = "admin"
dofile(dirs.installdir .. "/scripts/lua/inc/menu.lua")
prefs = ntop.getPrefs()
if not isEmptyString(message_info) then
print[[<div class="alert ]] print(message_severity) print[[" role="alert">]]
print[[<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>]]
print(message_info)
print[[</div>]]
end
print [[
<h2>]] print(i18n("prefs.runtime_prefs")) print[[</h2>
]]
if(false) then
io.write("------- SERVER ----------------\n")
tprint(_SERVER)
io.write("-------- GET ---------------\n")
tprint(_GET)
io.write("-------- POST ---------------\n")
tprint(_POST)
io.write("-----------------------\n")
end
if toboolean(_POST["show_advanced_prefs"]) ~= nil then
ntop.setPref(show_advanced_prefs_key, _POST["show_advanced_prefs"])
show_advanced_prefs = toboolean(_POST["show_advanced_prefs"])
notifyNtopng(show_advanced_prefs_key, _POST["show_advanced_prefs"])
else
show_advanced_prefs = toboolean(ntop.getPref(show_advanced_prefs_key))
if isEmptyString(show_advanced_prefs) then show_advanced_prefs = false end
end
if hasAlertsDisabled() then
alerts_disabled = true
end
local subpage_active, tab = prefsGetActiveSubpage(show_advanced_prefs, _GET["tab"])
-- ================================================================================
function printInterfaces()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.zmq_interfaces")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["ignored_interfaces"].title,
subpage_active.entries["ignored_interfaces"].description,
"ntopng.prefs.",
"ignored_interfaces",
"",
false, nil, nil, nil, {attributes={spellcheck="false", pattern="^([0-9]+,)*[0-9]+$", maxlength=32}})
prefsToggleButton(subpage_active, {
field = "toggle_dst_with_post_nat_dst",
default = "0",
pref = "override_dst_with_post_nat_dst",
})
prefsToggleButton(subpage_active, {
field = "toggle_src_with_post_nat_src",
default = "0",
pref = "override_src_with_post_nat_src",
})
prefsToggleButton(subpage_active, {
field = "toggle_src_and_dst_using_ports",
default = "0",
pref = "use_ports_to_determine_src_and_dst",
})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form> ]]
end
-- ================================================================================
function printAlerts()
print(
template.gen("modal_confirm_dialog.html", {
dialog={
id = "flushAlertsData",
action = "flushAlertsData()",
title = i18n("show_alerts.reset_alert_database"),
message = i18n("show_alerts.reset_alert_database_message") .. "?",
confirm = i18n("show_alerts.flush_data"),
confirm_button = "btn-danger",
}
})
)
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("show_alerts.alerts")..'</th></tr>')
if ntop.getPref("ntopng.prefs.disable_alerts_generation") == "1" then
showElements = true
else
showElements = false
end
local elementToSwitch = { "max_num_alerts_per_entity", "max_num_flow_alerts",
"row_alerts_retention_header", "row_alerts_settings_header", "row_alerts_security_header",
"row_toggle_remote_to_remote_alerts",
"row_toggle_ip_reassignment_alerts", "row_alerts_informative_header",
"row_toggle_device_first_seen_alert", "row_toggle_device_activation_alert", "row_toggle_pool_activation_alert", "row_toggle_quota_exceeded_alert",
"longlived_flow_duration", "elephant_flow_local_to_remote_bytes", "elephant_flow_remote_to_local_bytes"
}
if not subpage_active.entries["toggle_mysql_check_open_files_limit"].hidden then
elementToSwitch[#elementToSwitch+1] = "row_toggle_mysql_check_open_files_limit"
end
prefsToggleButton(subpage_active, {
field = "disable_alerts_generation",
default = "0",
to_switch = elementToSwitch,
on_value = "0", -- On means alerts enabled and thus disable_alerts_generation == 0
off_value = "1", -- Off for enabled alerts implies 1 for disable_alerts_generation
})
if ntop.getPrefs().are_alerts_enabled == true then
showElements = true
else
showElements = false
end
prefsToggleButton(subpage_active, {
field = "toggle_mysql_check_open_files_limit",
default = "1",
pref = "alerts.mysql_check_open_files_limit",
hidden = not showElements or subpage_active.entries["toggle_mysql_check_open_files_limit"].hidden,
})
print('<tr id="row_alerts_security_header" ')
if (showElements == false) then print(' style="display:none;"') end
print('><th colspan=2 class="info">'..i18n("prefs.security_alerts")..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_ip_reassignment_alerts",
pref = "ip_reassignment_alerts",
default = "0",
hidden = not showElements,
})
prefsToggleButton(subpage_active, {
field = "toggle_remote_to_remote_alerts",
pref = "remote_to_remote_alerts",
default = "0",
hidden = not showElements,
})
prefsInputFieldPrefs(subpage_active.entries["longlived_flow_duration"].title,
subpage_active.entries["longlived_flow_duration"].description,
"ntopng.prefs.", "longlived_flow_duration", 12 * 60 * 60 --[[ 12 hours --]],
"number", showElements, nil, nil, {min=1, max=60*60*24*7, tformat="mhd"})
prefsInputFieldPrefs(subpage_active.entries["elephant_flow_local_to_remote_bytes"].title,
subpage_active.entries["elephant_flow_local_to_remote_bytes"].description,
"ntopng.prefs.", "elephant_flow_local_to_remote_bytes", 1024 * 1024 * 1024 --[[ 1 GB --]],
"number", showElements, nil, nil, {min=1024, format_spec = FMT_TO_DATA_BYTES, tformat="kmg"})
prefsInputFieldPrefs(subpage_active.entries["elephant_flow_remote_to_local_bytes"].title,
subpage_active.entries["elephant_flow_remote_to_local_bytes"].description,
"ntopng.prefs.", "elephant_flow_remote_to_local_bytes", 1024 * 1024 * 1024 --[[ 1 GB --]],
"number", showElements, nil, nil, {min=1024, format_spec = FMT_TO_DATA_BYTES, tformat="kmg"})
print('<tr id="row_alerts_informative_header" ')
if (showElements == false) then print(' style="display:none;"') end
print('><th colspan=2 class="info">'..i18n("prefs.status_alerts")..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_device_first_seen_alert",
pref = "device_first_seen_alert",
default = "0",
hidden = not showElements,
redis_prefix = "ntopng.prefs.alerts.",
})
prefsToggleButton(subpage_active, {
field = "toggle_device_activation_alert",
pref = "device_connection_alert",
default = "0",
hidden = not showElements,
redis_prefix = "ntopng.prefs.alerts.",
})
prefsToggleButton(subpage_active, {
field = "toggle_pool_activation_alert",
pref = "pool_connection_alert",
default = "0",
hidden = not showElements,
redis_prefix = "ntopng.prefs.alerts.",
})
if ntop.isnEdge() then
prefsToggleButton(subpage_active, {
field = "toggle_quota_exceeded_alert",
pref = "quota_exceeded_alert",
default = "0",
hidden = not showElements,
redis_prefix = "ntopng.prefs.alerts.",
})
end
print('<tr id="row_alerts_retention_header" ')
if (showElements == false) then print(' style="display:none;"') end
print('><th colspan=2 class="info">'..i18n("prefs.alerts_retention")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["max_num_alerts_per_entity"].title, subpage_active.entries["max_num_alerts_per_entity"].description,
"ntopng.prefs.", "max_num_alerts_per_entity", prefs.max_num_alerts_per_entity, "number", showElements, false, nil, {min=1, --[[ TODO check min/max ]]})
prefsInputFieldPrefs(subpage_active.entries["max_num_flow_alerts"].title, subpage_active.entries["max_num_flow_alerts"].description,
"ntopng.prefs.", "max_num_flow_alerts", prefs.max_num_flow_alerts, "number", showElements, false, nil, {min=1, --[[ TODO check min/max ]]})
print('<tr><th colspan=2 style="text-align:right;">')
print('<button class="btn btn-default" type="button" onclick="$(\'#flushAlertsData\').modal(\'show\');" style="width:230px; float:left;">'..i18n("show_alerts.reset_alert_database")..'</button>')
print('<button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button>')
print('</th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>
<script>
function flushAlertsData() {
var params = {};
params.flush_alerts_data = "";
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
var form = paramsToForm('<form method="post"></form>', params);
form.appendTo('body').submit();
}
</script>
]]
end
-- ================================================================================
function printExternalAlertsReport()
if alerts_disabled then return end
print('<form method="post" id="external_alerts_form">')
print('<table class="table">')
local showElements = true
local alert_sev_labels = {i18n("prefs.errors"), i18n("prefs.errors_and_warnings"), i18n("prefs.all")}
local alert_sev_values = {"error", "warning", "info"}
if ntop.sendMail then -- only if sendmail is defined, and thus, supported
print('<tr><th colspan="2" class="info">'..i18n("prefs.email_notification")..'</th></tr>')
local elementToSwitch = {"row_email_notification_severity_preference", "email_sender", "email_recipient", "smtp_server", "smtp_username", "smtp_password", "alerts_test"}
prefsToggleButton(subpage_active, {
field = "toggle_email_notification",
pref = alert_endpoints.getAlertNotificationModuleEnableKey("email", true),
default = "0",
disabled = (showElements==false),
to_switch = elementToSwitch,
})
local showEmailNotificationPrefs = false
if ntop.getPref(alert_endpoints.getAlertNotificationModuleEnableKey("email")) == "1" then
showEmailNotificationPrefs = true
else
showEmailNotificationPrefs = false
end
multipleTableButtonPrefs(subpage_active.entries["slack_notification_severity_preference"].title, subpage_active.entries["slack_notification_severity_preference"].description,
alert_sev_labels, alert_sev_values, "error", "primary", "email_notification_severity_preference",
alert_endpoints.getAlertNotificationModuleSeverityKey("email"), nil, nil, nil, nil, showElements and showEmailNotificationPrefs)
prefsInputFieldPrefs(subpage_active.entries["email_notification_server"].title, subpage_active.entries["email_notification_server"].description,
"ntopng.prefs.alerts.", "smtp_server",
"", nil, showElements and showEmailNotificationPrefs, false, true, {attributes={spellcheck="false"}, required=true, pattern="^((smtp://)|(smtps://))?[a-zA-Z0-9-.]*(:[0-9]+)?$"})
prefsInputFieldPrefs(subpage_active.entries["email_notification_username"].title, subpage_active.entries["email_notification_username"].description,
"ntopng.prefs.alerts.", "smtp_username",
"", nil, showElements and showEmailNotificationPrefs, false, nil, {attributes={spellcheck="false"}, required=false})
prefsInputFieldPrefs(subpage_active.entries["email_notification_password"].title, subpage_active.entries["email_notification_password"].description,
"ntopng.prefs.alerts.", "smtp_password",
"", "password", showElements and showEmailNotificationPrefs, false, nil, {attributes={spellcheck="false"}, required=false})
prefsInputFieldPrefs(subpage_active.entries["email_notification_sender"].title, subpage_active.entries["email_notification_sender"].description,
"ntopng.prefs.alerts.", "email_sender",
"", nil, showElements and showEmailNotificationPrefs, false, nil, {attributes={spellcheck="false"}, pattern=email_peer_pattern, required=true})
prefsInputFieldPrefs(subpage_active.entries["email_notification_recipient"].title, subpage_active.entries["email_notification_recipient"].description,
"ntopng.prefs.alerts.", "email_recipient",
"", nil, showElements and showEmailNotificationPrefs, false, nil, {attributes={spellcheck="false"}, pattern=email_peer_pattern, required=true})
print('<tr id="alerts_test" style="' .. ternary(showEmailNotificationPrefs, "", "display:none;").. '"><td><button class="btn btn-default disable-on-dirty" type="button" onclick="sendTestEmail();" style="width:230px; float:left;">'..i18n("prefs.send_test_mail")..'</button></td></tr>')
end -- ntop.sendMail
print('<tr><th colspan=2 class="info"><i class="fa fa-slack" aria-hidden="true"></i> '..i18n('prefs.slack_integration')..'</th></tr>')
local elementToSwitchSlack = {"row_slack_notification_severity_preference", "slack_sender_username", "slack_webhook", "slack_test", "slack_channels"}
prefsToggleButton(subpage_active, {
field = "toggle_slack_notification",
pref = alert_endpoints.getAlertNotificationModuleEnableKey("slack", true),
default = "0",
disabled = showElements==false,
to_switch = elementToSwitchSlack,
})
local showSlackNotificationPrefs = false
if ntop.getPref(alert_endpoints.getAlertNotificationModuleEnableKey("slack")) == "1" then
showSlackNotificationPrefs = true
else
showSlackNotificationPrefs = false
end
multipleTableButtonPrefs(subpage_active.entries["slack_notification_severity_preference"].title, subpage_active.entries["slack_notification_severity_preference"].description,
alert_sev_labels, alert_sev_values, "error", "primary", "slack_notification_severity_preference",
alert_endpoints.getAlertNotificationModuleSeverityKey("slack"), nil, nil, nil, nil, showElements and showSlackNotificationPrefs)
prefsInputFieldPrefs(subpage_active.entries["sender_username"].title, subpage_active.entries["sender_username"].description,
"ntopng.prefs.alerts.", "slack_sender_username",
"ntopng Webhook", nil, showElements and showSlackNotificationPrefs, false, nil, {attributes={spellcheck="false"}, required=true})
prefsInputFieldPrefs(subpage_active.entries["slack_webhook"].title, subpage_active.entries["slack_webhook"].description,
"ntopng.prefs.alerts.", "slack_webhook",
"", nil, showElements and showSlackNotificationPrefs, true, true, {attributes={spellcheck="false"}, style={width="43em"}, required=true, pattern=getURLPattern()})
-- Channel settings
print('<tr id="slack_channels" style="' .. ternary(showSlackNotificationPrefs, "", "display:none;").. '"><td><strong>' .. i18n("prefs.slack_channel_names") .. '</strong><p><small>' .. i18n("prefs.slack_channel_names_descr") .. '</small></p></td><td><table class="table table-bordered table-condensed"><tr><th>'.. i18n("prefs.alert_entity") ..'</th><th>' .. i18n("prefs.slack_channel") ..'</th></tr>')
for entity_type_raw, entity in pairsByKeys(alert_consts.alert_entities) do
local entity_type = alert_consts.alertEntity(entity_type_raw)
local label = alert_consts.alertEntityLabel(entity_type)
local channel = slack_utils.getChannelName(entity_type_raw)
print('<tr><td>'.. label ..'</td><td><div class="form-group" style="margin:0"><input class="form-control input-sm" name="slack_ch_'.. entity_type ..'" pattern="[^\' \']*" value="'.. channel ..'"></div></td></tr>')
end
print('</table></td></tr>')
print('<tr id="slack_test" style="' .. ternary(showSlackNotificationPrefs, "", "display:none;").. '"><td><button class="btn btn-default disable-on-dirty" type="button" onclick="sendTestSlack();" style="width:230px; float:left;">'..i18n("prefs.send_test_slack")..'</button></td></tr>')
if ntop.syslog then
print('<tr><th colspan="2" class="info">'..i18n("prefs.syslog_notification")..'</th></tr>')
local alertsEnabled = showElements
local elementToSwitch = {"row_syslog_alert_format"}
prefsToggleButton(subpage_active, {
field = "toggle_alert_syslog",
pref = alert_endpoints.getAlertNotificationModuleEnableKey("syslog", true),
default = "0",
disabled = alertsEnabled == false,
to_switch = elementToSwitch,
})
local format_labels = {i18n("prefs.syslog_alert_format_plaintext"), i18n("prefs.syslog_alert_format_json")}
local format_values = {"plaintext", "json"}
if ntop.getPref(alert_endpoints.getAlertNotificationModuleEnableKey("syslog")) == "0" then
alertsEnabled = false
end
retVal = multipleTableButtonPrefs(subpage_active.entries["syslog_alert_format"].title,
subpage_active.entries["syslog_alert_format"].description,
format_labels, format_values,
"plaintext",
"primary",
"syslog_alert_format",
"ntopng.prefs.syslog_alert_format", nil,
nil, nil, nil, alertsEnabled)
end
if(ntop.isPro() and hasNagiosSupport()) then
print('<tr><th colspan="2" class="info">'..i18n("prefs.nagios_integration")..'</th></tr>')
local alertsEnabled = showElements
local elementToSwitch = {"nagios_nsca_host","nagios_nsca_port","nagios_send_nsca_executable",
"nagios_send_nsca_config","nagios_host_name","nagios_service_name",
"row_nagios_notification_severity_preference"}
prefsToggleButton(subpage_active, {
field = "toggle_alert_nagios",
pref = alert_endpoints.getAlertNotificationModuleEnableKey("nagios", true),
default = "0",
disabled = alertsEnabled == false,
to_switch = elementToSwitch,
})
local showNagiosElements = showElements
if ntop.getPref(alert_endpoints.getAlertNotificationModuleEnableKey("nagios")) == "0" then
showNagiosElements = false
end
showNagiosElements = alertsEnabled and showNagiosElements
multipleTableButtonPrefs(subpage_active.entries["slack_notification_severity_preference"].title, subpage_active.entries["slack_notification_severity_preference"].description,
alert_sev_labels, alert_sev_values, "error", "primary", "nagios_notification_severity_preference",
alert_endpoints.getAlertNotificationModuleSeverityKey("nagios"), nil, nil, nil, nil, showNagiosElements, false)
prefsInputFieldPrefs(subpage_active.entries["nagios_nsca_host"].title, subpage_active.entries["nagios_nsca_host"].description, "ntopng.prefs.", "nagios_nsca_host", prefs.nagios_nsca_host, nil, showNagiosElements, false)
prefsInputFieldPrefs(subpage_active.entries["nagios_nsca_port"].title, subpage_active.entries["nagios_nsca_port"].description, "ntopng.prefs.", "nagios_nsca_port", prefs.nagios_nsca_port, "number", showNagiosElements, false, nil, {min=1, max=65535})
prefsInputFieldPrefs(subpage_active.entries["nagios_send_nsca_executable"].title, subpage_active.entries["nagios_send_nsca_executable"].description, "ntopng.prefs.", "nagios_send_nsca_executable", prefs.nagios_send_nsca_executable, nil, showNagiosElements, false)
prefsInputFieldPrefs(subpage_active.entries["nagios_send_nsca_config"].title, subpage_active.entries["nagios_send_nsca_config"].description, "ntopng.prefs.", "nagios_send_nsca_config", prefs.nagios_send_nsca_conf, nil, showNagiosElements, false)
prefsInputFieldPrefs(subpage_active.entries["nagios_host_name"].title, subpage_active.entries["nagios_host_name"].description, "ntopng.prefs.", "nagios_host_name", prefs.nagios_host_name, nil, showNagiosElements, false)
prefsInputFieldPrefs(subpage_active.entries["nagios_service_name"].title, subpage_active.entries["nagios_service_name"].description, "ntopng.prefs.", "nagios_service_name", prefs.nagios_service_name, nil, showNagiosElements)
end
-- Webhook
print('<tr><th colspan=2 class="info">'..i18n('prefs.webhook_notification')..'</th></tr>')
local elementToSwitchWebhook = {"row_webhook_notification_severity_preference", "webhook_url", "webhook_sharedsecret", "webhook_test", "webhook_username", "webhook_password"}
prefsToggleButton(subpage_active, {
field = "toggle_webhook_notification",
pref = alert_endpoints.getAlertNotificationModuleEnableKey("webhook", true),
default = "0",
disabled = showElements==false,
to_switch = elementToSwitchWebhook,
})
local showWebhookNotificationPrefs = false
if ntop.getPref(alert_endpoints.getAlertNotificationModuleEnableKey("webhook")) == "1" then
showWebhookNotificationPrefs = true
else
showWebhookNotificationPrefs = false
end
multipleTableButtonPrefs(subpage_active.entries["webhook_notification_severity_preference"].title, subpage_active.entries["webhook_notification_severity_preference"].description,
alert_sev_labels, alert_sev_values, "error", "primary", "webhook_notification_severity_preference",
alert_endpoints.getAlertNotificationModuleSeverityKey("webhook"), nil, nil, nil, nil, showElements and showWebhookNotificationPrefs)
prefsInputFieldPrefs(subpage_active.entries["webhook_url"].title, subpage_active.entries["webhook_url"].description,
"ntopng.prefs.alerts.", "webhook_url",
"", nil, showElements and showWebhookNotificationPrefs, true, true, {attributes={spellcheck="false"}, style={width="43em"}, required=true, pattern=getURLPattern()})
prefsInputFieldPrefs(subpage_active.entries["webhook_sharedsecret"].title, subpage_active.entries["webhook_sharedsecret"].description,
"ntopng.prefs.alerts.", "webhook_sharedsecret",
"", nil, showElements and showWebhookNotificationPrefs, false, nil, {attributes={spellcheck="false"}, required=false})
prefsInputFieldPrefs(subpage_active.entries["webhook_username"].title, subpage_active.entries["webhook_username"].description,
"ntopng.prefs.alerts.", "webhook_username",
"", false, showElements and showWebhookNotificationPrefs, nil, nil, {attributes={spellcheck="false"}, pattern="[^\\s]+", required=false})
prefsInputFieldPrefs(subpage_active.entries["webhook_password"].title, subpage_active.entries["webhook_password"].description,
"ntopng.prefs.alerts.", "webhook_password",
"", "password", showElements and showWebhookNotificationPrefs, nil, nil, {attributes={spellcheck="false"}, pattern="[^\\s]+", required=false})
print('<tr id="webhook_test" style="' .. ternary(showWebhookNotificationPrefs, "", "display:none;").. '"><td><button class="btn btn-default disable-on-dirty" type="button" onclick="sendTestWebhook();" style="width:230px; float:left;">'..i18n("prefs.send_test_webhook")..'</button></td></tr>')
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form> ]]
print[[<script>
function sendTestEmail() {
var params = {};
params.send_test_email = "";
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
var form = paramsToForm('<form method="post"></form>', params);
form.appendTo('body').submit();
}
function sendTestSlack() {
var params = {};
params.send_test_slack = "";
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
var form = paramsToForm('<form method="post"></form>', params);
form.appendTo('body').submit();
}
function sendTestWebhook() {
var params = {};
params.send_test_webhook = "";
params.csrf = "]] print(ntop.getRandomCSRFValue()) print[[";
var form = paramsToForm('<form method="post"></form>', params);
form.appendTo('body').submit();
}
function replace_email_special_characters(event) {
var form = $(this);
// e.g. when form is invalid
if(event.isDefaultPrevented())
return;
// this is necessary to escape "<" and ">" which are blocked on the backend to prevent injection
$("[name='email_sender'],[name='email_recipient']", form).each(function() {
var name = $(this).attr("name");
$(this).removeAttr("name");
$('<input type="hidden" name="' + name + '">')
.val(encodeURI($(this).val()))
.appendTo(form);
});
}
$(function() {
$("#external_alerts_form").submit(replace_email_special_characters);
});
</script>]]
end
-- ================================================================================
function printProtocolPrefs()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">HTTP</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_top_sites",
pref = "host_top_sites_creation",
default = "0",
})
--[[
print('<tr><th colspan=2 class="info">TCP</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["ewma_alpha_percent"].title, subpage_active.entries["ewma_alpha_percent"].description,
"ntopng.prefs.", "ewma_alpha_percent", prefs.ewma_alpha_percent, "number",
true,
nil, nil, {min=1, max=99,})
--]]
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form> ]]
end
-- ================================================================================
function printNetworkDiscovery()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.network_discovery")..'</th></tr>')
local elementToSwitch = {"network_discovery_interval"}
prefsToggleButton(subpage_active, {
field = "toggle_network_discovery",
default = "0",
pref = "is_periodic_network_discovery_enabled",
to_switch = elementToSwitch,
})
local showNetworkDiscoveryInterval = false
if ntop.getPref("ntopng.prefs.is_periodic_network_discovery_enabled") == "1" then
showNetworkDiscoveryInterval = true
end
local interval = ntop.getPref("ntopng.prefs.network_discovery_interval")
if isEmptyString(interval) then -- set a default value
interval = 15 * 60 -- 15 minutes
ntop.setPref("ntopng.prefs.network_discovery_interval", tostring(interval))
end
prefsInputFieldPrefs(subpage_active.entries["network_discovery_interval"].title, subpage_active.entries["network_discovery_interval"].description,
"ntopng.prefs.", "network_discovery_interval", interval, "number", showNetworkDiscoveryInterval, nil, nil, {min=60 * 15, tformat="mhd"})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
function printTelemetry()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.telemetry")..'</th></tr>')
local t_labels = {i18n("prefs.telemetry_do_not_contribute")..' <i class="fa fa-frown-o"></i>',
i18n("prefs.telemetry_contribute")..' <i class="fa fa-heart"></i>'}
local t_values = {"0", "1"}
local elementToSwitch = {"telemetry_email"}
local showElementArray = {false, true}
multipleTableButtonPrefs(subpage_active.entries["toggle_send_telemetry_data"].title,
subpage_active.entries["toggle_send_telemetry_data"].description,
t_labels, t_values,
"", -- leave the default empty so one is forced to either chose opt-in or opt-out
"primary", "toggle_send_telemetry_data", "ntopng.prefs.send_telemetry_data", nil,
elementToSwitch, showElementArray, javascriptAfterSwitch, true--[[show]])
prefsInputFieldPrefs(subpage_active.entries["telemetry_email"].title,
subpage_active.entries["telemetry_email"].description,
"ntopng.prefs.",
"telemetry_email",
"",
false,
telemetry_utils.telemetry_enabled(),
nil, nil, {attributes={spellcheck="false"}, pattern=email_peer_pattern, required=false})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
function printRecording()
local n2disk_info = recording_utils.getN2diskInfo()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.license")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["n2disk_license"].title, subpage_active.entries["n2disk_license"].description.."<br>"
..ternary(n2disk_info.version ~= nil, i18n("prefs.n2disk_license_version", {version=n2disk_info.version}).."<br>", "")
..ternary(n2disk_info.systemid ~= nil, i18n("prefs.n2disk_license_systemid", {systemid=n2disk_info.systemid}), ""),
"ntopng.prefs.", "n2disk_license",
ternary(n2disk_info.license ~= nil, n2disk_info.license, ""),
false, nil, nil, nil, {style={width="25em;"}, min = 50, max = 64,
pattern = getLicensePattern()})
print('<tr><th colspan=2 class="info">'..i18n("traffic_recording.settings")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["max_extracted_pcap_bytes"].title,
subpage_active.entries["max_extracted_pcap_bytes"].description,
"ntopng.prefs.", "max_extracted_pcap_bytes", prefs.max_extracted_pcap_bytes,
"number", true, nil, nil, {min=10*1024*1024, format_spec = FMT_TO_DATA_BYTES, tformat="mg"})
-- ######################
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
function printRemoteAssitance()
if not remote_assistance.isAvailable() then
return
end
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("remote_assistance.remote_assistance")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["n2n_supernode"].title,
subpage_active.entries["n2n_supernode"].description,
"ntopng.prefs.remote_assistance.", "supernode", remote_assistance.getSupernode(), nil,
true, nil, nil, {attributes = {pattern = "[0-9.\\-A-Za-z]+(:[0-9]+)?", required = "required"}})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
function printDataRetention()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.data_retention")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["data_retention"].title,
subpage_active.entries["data_retention"].description,
"ntopng.prefs.", "data_retention_days", data_retention_utils.getDefaultRetention(), "number", nil, nil, nil, {min=1, max=365 * 10})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
function printMisc()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.web_user_interface")..'</th></tr>')
if prefs.is_autologout_enabled == true then
prefsToggleButton(subpage_active, {
field = "toggle_autologout",
default = "1",
pref = "is_autologon_enabled",
})
end
prefsInputFieldPrefs(subpage_active.entries["max_ui_strlen"].title, subpage_active.entries["max_ui_strlen"].description,
"ntopng.prefs.", "max_ui_strlen", prefs.max_ui_strlen, "number", nil, nil, nil, {min=3, max=128})
prefsInputFieldPrefs(subpage_active.entries["mgmt_acl"].title, subpage_active.entries["mgmt_acl"].description,
"ntopng.prefs.",
"http_acl_management_port",
"", false, nil, nil, nil, {style = {width = "25em;"},
attributes = {spellcheck = "false", maxlength = 64, pattern = getACLPattern()}})
prefsInputFieldPrefs(subpage_active.entries["google_apis_browser_key"].title, subpage_active.entries["google_apis_browser_key"].description,
"ntopng.prefs.",
"google_apis_browser_key",
"", false, nil, nil, nil, {style={width="25em;"}, attributes={spellcheck="false"} --[[ Note: Google API keys can vary in format ]] })
-- ######################
print('<tr><th colspan=2 class="info">'..i18n("prefs.report")..'</th></tr>')
local t_labels = {i18n("bytes"), i18n("packets")}
local t_values = {"bps", "pps"}
multipleTableButtonPrefs(subpage_active.entries["toggle_thpt_content"].title, subpage_active.entries["toggle_thpt_content"].description,
t_labels, t_values, "bps", "primary", "toggle_thpt_content", "ntopng.prefs.thpt_content")
-- ######################
if ntop.isPro() then
t_labels = {i18n("topk_heuristic.precision.disabled"),
i18n("topk_heuristic.precision.more_accurate"),
i18n("topk_heuristic.precision.less_accurate"),
i18n("topk_heuristic.precision.aggressive")}
t_values = {"disabled", "more_accurate", "accurate", "aggressive"}
multipleTableButtonPrefs(subpage_active.entries["topk_heuristic_precision"].title,
subpage_active.entries["topk_heuristic_precision"].description,
t_labels, t_values, "more_accurate", "primary", "topk_heuristic_precision",
"ntopng.prefs.topk_heuristic_precision")
end
-- ######################
if(haveAdminPrivileges()) then
print('<tr><th colspan=2 class="info">'..i18n("hosts")..'</th></tr>')
local h_labels = {i18n("prefs.no_host_mask"), i18n("prefs.local_host_mask"), i18n("prefs.remote_host_mask")}
local h_values = {"0", "1", "2"}
multipleTableButtonPrefs(subpage_active.entries["toggle_host_mask"].title,
subpage_active.entries["toggle_host_mask"].description,
h_labels, h_values, "0", "primary", "toggle_host_mask", "ntopng.prefs.host_mask")
prefsToggleButton(subpage_active, {
field = "toggle_arp_matrix_generation",
default = "0",
pref = "arp_matrix_generation",
to_switch = nil,
})
end
-- #####################
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>]]
end
-- ================================================================================
local function printAuthDuration()
print('<tr><th colspan=2 class="info">'..i18n("prefs.authentication_duration")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["authentication_duration"].title, subpage_active.entries["authentication_duration"].description,
"ntopng.prefs.","auth_session_duration",
prefs.auth_session_duration, "number", true, nil, nil,
{min = 60 --[[ 1 minute --]], max = 86400 * 7 --[[ 7 days --]],
tformat="mhd"})
prefsToggleButton(subpage_active, {
field = "toggle_auth_session_midnight_expiration",
default = "0",
pref = "auth_session_midnight_expiration",
})
end
-- ================================================================================
local function printLdapAuth()
if not ntop.isPro() then return end
print('<tr><th colspan=2 class="info">'..i18n("prefs.ldap_authentication")..'</th></tr>')
local elementToSwitch = {"row_multiple_ldap_account_type", "row_toggle_ldap_anonymous_bind","server","bind_dn", "bind_pwd", "ldap_server_address", "search_path", "user_group", "admin_group", "row_toggle_ldap_referrals"}
local javascriptAfterSwitch = "";
javascriptAfterSwitch = javascriptAfterSwitch.." if($(\"#toggle_ldap_auth_input\").val() == \"1\") {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." if($(\"#toggle_ldap_anonymous_bind_input\").val() == \"0\") {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#bind_dn\").css(\"display\",\"table-row\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#bind_pwd\").css(\"display\",\"table-row\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." } else {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#bind_dn\").css(\"display\",\"none\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#bind_pwd\").css(\"display\",\"none\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." }\n"
javascriptAfterSwitch = javascriptAfterSwitch.." }\n"
prefsToggleButton(subpage_active, {
field = auth_toggles.ldap,
pref = "ldap.auth_enabled",
default = "0",
to_switch = elementToSwitch,
js_after_switch = javascriptAfterSwitch,
})
local showElements = (ntop.getPref("ntopng.prefs.ldap.auth_enabled") == "1")
local labels_account = {i18n("prefs.posix"), i18n("prefs.samaccount")}
local values_account = {"posix","samaccount"}
multipleTableButtonPrefs(subpage_active.entries["multiple_ldap_account_type"].title, subpage_active.entries["multiple_ldap_account_type"].description,
labels_account, values_account, "posix", "primary", "multiple_ldap_account_type", "ntopng.prefs.ldap.account_type", nil, nil, nil, nil, showElements)
prefsInputFieldPrefs(subpage_active.entries["ldap_server_address"].title, subpage_active.entries["ldap_server_address"].description,
"ntopng.prefs.ldap", "ldap_server_address", "ldap://localhost:389", nil, showElements, true, true, {attributes={pattern="ldap(s)?://[0-9.\\-A-Za-z]+(:[0-9]+)?", spellcheck="false", required="required", maxlength=255}})
local elementToSwitchBind = {"bind_dn","bind_pwd"}
prefsToggleButton(subpage_active, {
field = "toggle_ldap_anonymous_bind",
default = "1",
pref = "ldap.anonymous_bind",
to_switch = elementToSwitchBind,
reverse_switch = true,
hidden = not showElements,
})
local showEnabledAnonymousBind = false
if ntop.getPref("ntopng.prefs.ldap.anonymous_bind") == "0" then
showEnabledAnonymousBind = true
end
local showElementsBind = showElements
if showElements == true then
showElementsBind = showEnabledAnonymousBind
end
prefsInputFieldPrefs(subpage_active.entries["bind_dn"].title, subpage_active.entries["bind_dn"].description .. "\"CN=ntop_users,DC=ntop,DC=org,DC=local\".", "ntopng.prefs.ldap", "bind_dn", "", nil, showElementsBind, true, false, {attributes={spellcheck="false", maxlength=255}})
prefsInputFieldPrefs(subpage_active.entries["bind_pwd"].title, subpage_active.entries["bind_pwd"].description, "ntopng.prefs.ldap", "bind_pwd", "", "password", showElementsBind, true, false, {attributes={maxlength=255}})
prefsInputFieldPrefs(subpage_active.entries["search_path"].title, subpage_active.entries["search_path"].description, "ntopng.prefs.ldap", "search_path", "", "text", showElements, nil, nil, {attributes={spellcheck="false", maxlength=255}})
prefsInputFieldPrefs(subpage_active.entries["user_group"].title, subpage_active.entries["user_group"].description, "ntopng.prefs.ldap", "user_group", "", "text", showElements, nil, nil, {attributes={spellcheck="false", maxlength=255}})
prefsInputFieldPrefs(subpage_active.entries["admin_group"].title, subpage_active.entries["admin_group"].description, "ntopng.prefs.ldap", "admin_group", "", "text", showElements, nil, nil, {attributes={spellcheck="false", maxlength=255}})
prefsToggleButton(subpage_active, {
field = "toggle_ldap_referrals",
default = "1",
pref = "ldap.follow_referrals",
reverse_switch = true,
hidden = not showElements,
})
end
-- #####################
local function printRadiusAuth()
if subpage_active.entries["toggle_radius_auth"].hidden then
return
end
print('<tr><th colspan=2 class="info">'..i18n("prefs.radius_auth")..'</th></tr>')
local elementToSwitch = {"radius_server_address", "radius_secret", "radius_admin_group"}
prefsToggleButton(subpage_active, {
field = auth_toggles.radius,
pref = "radius.auth_enabled",
default = "0",
to_switch = elementToSwitch,
})
local showElements = (ntop.getPref("ntopng.prefs.radius.auth_enabled") == "1")
prefsInputFieldPrefs(subpage_active.entries["radius_server"].title, subpage_active.entries["radius_server"].description,
"ntopng.prefs.radius", "radius_server_address", "127.0.0.1:1812", nil, showElements, true, false,
{attributes={spellcheck="false", maxlength=255, required="required", pattern="[0-9.\\-A-Za-z]+:[0-9]+"}})
-- https://github.com/FreeRADIUS/freeradius-client/blob/7b7473ab78ca5f99e083e5e6c16345b7c2569db1/include/freeradius-client.h#L395
prefsInputFieldPrefs(subpage_active.entries["radius_secret"].title, subpage_active.entries["radius_secret"].description,
"ntopng.prefs.radius", "radius_secret", "", "password", showElements, true, false,
{attributes={spellcheck="false", maxlength=48, required="required"}})
prefsInputFieldPrefs(subpage_active.entries["radius_admin_group"].title, subpage_active.entries["radius_admin_group"].description,
"ntopng.prefs.radius", "radius_admin_group", "", nil, showElements, true, false,
{attributes={spellcheck="false", maxlength=255, pattern="[^\\s]+"}})
end
-- #####################
local function printHttpAuth()
print('<tr><th colspan=2 class="info">'..i18n("prefs.http_auth")..'</th></tr>')
local elementToSwitch = {"http_auth_url"}
prefsToggleButton(subpage_active, {
field = auth_toggles.http,
pref = "http_authenticator.auth_enabled",
default = "0",
to_switch = elementToSwitch,
})
local showElements = (ntop.getPref("ntopng.prefs.http_authenticator.auth_enabled") == "1")
prefsInputFieldPrefs(subpage_active.entries["http_auth_server"].title, subpage_active.entries["http_auth_server"].description,
"ntopng.prefs.http_authenticator", "http_auth_url", "", nil, showElements, true, true --[[ allowUrls ]],
{attributes={spellcheck="false", maxlength=255, required="required", pattern=getURLPattern()}})
end
-- #####################
local function printLocalAuth()
print('<tr><th colspan=2 class="info">'..i18n("prefs.local_auth")..'</th></tr>')
prefsToggleButton(subpage_active, {
field = auth_toggles["local"],
pref = "local.auth_enabled",
default = "1",
})
end
-- #####################
function printAuthentication()
print('<form method="post">')
print('<table class="table">')
local entries = subpage_active.entries
printAuthDuration()
-- Note: order must correspond to evaluation order in Ntop.cpp
print('<tr><th class="info" colspan="2">'..i18n("prefs.client_x509_auth")..'</th></tr>')
prefsToggleButton(subpage_active,{
field = "toggle_client_x509_auth",
default = "0",
pref = "is_client_x509_auth_enabled",
})
if not entries.toggle_ldap_auth.hidden then
printLdapAuth()
end
if not entries.toggle_radius_auth.hidden then
printRadiusAuth()
end
if not entries.toggle_http_auth.hidden then
printHttpAuth()
end
if not entries.toggle_local_auth.hidden then
printLocalAuth()
end
if not ntop.isnEdge() then
prefsInformativeField(i18n("notes"), i18n("prefs.auth_methods_order"))
else
prefsInformativeField(i18n("notes"), i18n("nedge.authentication_gui_and_captive_portal",
{product = product, url = ntop.getHttpPrefix() .. "/lua/pro/nedge/system_setup/captive_portal.lua"}))
end
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />]]
print('</form>')
end
-- ================================================================================
function printInMemory()
print('<form id="localRemoteTimeoutForm" method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.stats_reset")..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_midnight_stats_reset",
default = "0",
pref = "midnight_stats_reset_enabled",
})
print('<tr><th colspan=2 class="info">'..i18n("prefs.local_hosts_cache_settings")..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_local_host_cache_enabled",
default = "1",
pref = "is_local_host_cache_enabled",
to_switch = {"local_host_cache_duration","row_toggle_active_local_host_cache_enabled","active_local_host_cache_interval"},
})
local showLocalHostCacheInterval = false
if ntop.getPref("ntopng.prefs.is_local_host_cache_enabled") == "1" then
showLocalHostCacheInterval = true
end
prefsInputFieldPrefs(subpage_active.entries["local_host_cache_duration"].title, subpage_active.entries["local_host_cache_duration"].description,
"ntopng.prefs.","local_host_cache_duration", prefs.local_host_cache_duration, "number", showLocalHostCacheInterval, nil, nil, {min=60, tformat="mhd"})
prefsToggleButton(subpage_active, {
field = "toggle_active_local_host_cache_enabled",
default = "0",
pref = "is_active_local_host_cache_enabled",
to_switch = {"active_local_host_cache_interval"},
})
local showActiveLocalHostCacheInterval = false
if ntop.getPref("ntopng.prefs.is_active_local_host_cache_enabled") == "1" then
showActiveLocalHostCacheInterval = true
end
prefsInputFieldPrefs(subpage_active.entries["active_local_host_cache_interval"].title, subpage_active.entries["active_local_host_cache_interval"].description,
"ntopng.prefs.", "active_local_host_cache_interval", prefs.active_local_host_cache_interval or 3600, "number", showActiveLocalHostCacheInterval, nil, nil, {min=60, tformat="mhd"})
print('</table>')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.idle_timeout_settings")..'</th></tr>')
prefsInputFieldPrefs(subpage_active.entries["local_host_max_idle"].title, subpage_active.entries["local_host_max_idle"].description,
"ntopng.prefs.","local_host_max_idle", prefs.local_host_max_idle, "number", nil, nil, nil,
{min=1, max=86400, tformat="smh", attributes={["data-localremotetimeout"]="localremotetimeout"}})
prefsInputFieldPrefs(subpage_active.entries["non_local_host_max_idle"].title, subpage_active.entries["non_local_host_max_idle"].description,
"ntopng.prefs.", "non_local_host_max_idle", prefs.non_local_host_max_idle, "number", nil, nil, nil,
{min=1, max=86400, tformat="smh"})
prefsInputFieldPrefs(subpage_active.entries["flow_max_idle"].title, subpage_active.entries["flow_max_idle"].description,
"ntopng.prefs.", "flow_max_idle", prefs.flow_max_idle, "number", nil, nil, nil,
{min=1, max=3600, tformat="smh"})
prefsInputFieldPrefs(subpage_active.entries["housekeeping_frequency"].title,
subpage_active.entries["housekeeping_frequency"].description,
"ntopng.prefs.", "housekeeping_frequency", prefs.housekeeping_frequency, "number", nil, nil, nil, {min = 1, max = 60})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>
<script>
function localRemoteTimeoutValidator() {
var form = $("#localRemoteTimeoutForm");
var local_timeout = resol_selector_get_raw($("input[name='local_host_max_idle']", form));
var remote_timeout = resol_selector_get_raw($("input[name='non_local_host_max_idle']", form));
if ((local_timeout != null) && (remote_timeout != null)) {
if (local_timeout < remote_timeout)
return false;
}
return true;
}
var idleFormValidatorOptions = {
disable: true,
custom: {
localremotetimeout: localRemoteTimeoutValidator,
}, errors: {
localremotetimeout: "Cannot be less then Remote Host Idle Timeout",
}
}
$("#localRemoteTimeoutForm")
.validator(idleFormValidatorOptions);
/* Retrigger the validation every second to clear outdated errors */
setInterval(function() {
$("#localRemoteTimeoutForm").data("bs.validator").validate();
}, 1000);
</script>
]]
end
-- ================================================================================
function printStatsTimeseries()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n('prefs.timeseries_database')..'</th></tr>')
local elementToSwitch = {"ts_post_data_url", "influx_dbname", "influx_retention", "row_toggle_influx_auth", "influx_username", "influx_password", "row_ts_high_resolution"}
local showElementArray = {false, true, false}
local javascriptAfterSwitch = "";
javascriptAfterSwitch = javascriptAfterSwitch.." if($(\"#id-toggle-timeseries_driver\").val() == \"influxdb\") {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." if($(\"#toggle_influx_auth_input\").val() == \"1\") {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#influx_username\").css(\"display\",\"table-row\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#influx_password\").css(\"display\",\"table-row\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." } else {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#influx_username\").css(\"display\",\"none\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#influx_password\").css(\"display\",\"none\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." }\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#old_rrd_files_retention\").css(\"display\",\"none\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." } else if($(\"#id-toggle-timeseries_driver\").val() == \"rrd\") {\n"
javascriptAfterSwitch = javascriptAfterSwitch.." $(\"#old_rrd_files_retention\").css(\"display\",\"table-row\");\n"
javascriptAfterSwitch = javascriptAfterSwitch.." }\n"
local active_driver = "rrd"
local influx_active = false
if not ntop.isWindows() then
multipleTableButtonPrefs(subpage_active.entries["multiple_timeseries_database"].title,
subpage_active.entries["multiple_timeseries_database"].description,
{"RRD", "InfluxDB", "Prometheus [Export Only]"}, {"rrd", "influxdb", "prometheus"},
"rrd",
"primary",
"timeseries_driver",
"ntopng.prefs.timeseries_driver", nil,
elementToSwitch, showElementArray, javascriptAfterSwitch, true--[[show]])
active_driver = ntop.getPref("ntopng.prefs.timeseries_driver")
influx_active = (active_driver == "influxdb")
end
prefsInputFieldPrefs(subpage_active.entries["influxdb_url"].title,
subpage_active.entries["influxdb_url"].description,
"ntopng.prefs.",
"ts_post_data_url",
"http://localhost:8086",
false, influx_active, nil, nil, {attributes={spellcheck="false"}, pattern=getURLPattern(), required=true})
if ntop.isnEdge() and ntop.getPref("ntopng.prefs.influx_dbname") == "ntopng edge" then
-- Fixes issue #1939 with wrong deployed nedge db name
ntop.delCache("ntopng.prefs.influx_dbname")
end
prefsInputFieldPrefs(subpage_active.entries["influxdb_dbname"].title, subpage_active.entries["influxdb_dbname"].description,
"ntopng.prefs.", "influx_dbname", product:gsub(' ' , '_'), nil, influx_active, nil, nil, {pattern="[A-z,0-9,_]+"})
prefsToggleButton(subpage_active, {
field = "toggle_influx_auth",
default = "0",
pref = "influx_auth_enabled",
to_switch = {"influx_username", "influx_password"},
hidden = not influx_active,
})
local auth_enabled = influx_active and (ntop.getPref("ntopng.prefs.influx_auth_enabled") == "1")
prefsInputFieldPrefs(subpage_active.entries["influxdb_username"].title, subpage_active.entries["influxdb_username"].description,
"ntopng.prefs.",
"influx_username", "",
false, auth_enabled, nil, nil, {attributes={spellcheck="false"}, pattern="[^\\s]+"})
prefsInputFieldPrefs(subpage_active.entries["influxdb_password"].title, subpage_active.entries["influxdb_password"].description,
"ntopng.prefs.",
"influx_password", "",
"password", auth_enabled, nil, nil, {attributes={spellcheck="false"}, pattern="[^\\s]+"})
local ts_slots_labels = {"10s", "30s", "1m", "5m"}
local ts_slots_values = {"10", "30", "60", "300"}
-- Currently, high-resolution-timeseries seem to only work when the default housekeeping frequency is in place.
-- As a TODO, it would be nice to relax this assumption.
local has_custom_housekeeping = (tonumber(ntop.getPref("ntopng.prefs.housekeeping_frequency")) or 5) ~= 5
multipleTableButtonPrefs(subpage_active.entries["timeseries_resolution_resolution"].title,
subpage_active.entries["timeseries_resolution_resolution"].description .. ternary(has_custom_housekeeping, "<br>" .. i18n("prefs.note_timeseries_resolution_disabled", {pref=i18n("prefs.housekeeping_frequency_title")}), ""),
ts_slots_labels, ts_slots_values,
"60",
"primary",
"ts_high_resolution",
"ntopng.prefs.ts_high_resolution", has_custom_housekeeping,
nil, nil, nil, influx_active)
print('<tr><th colspan=2 class="info">'..i18n('prefs.interfaces_timeseries')..'</th></tr>')
-- TODO: make also per-category interface RRDs
local l7_rrd_labels = {i18n("prefs.none"),
i18n("prefs.per_protocol"),
i18n("prefs.per_category"),
i18n("prefs.both")
}
local l7_rrd_values = {"none",
"per_protocol",
"per_category",
"both"}
local elementToSwitch = { }
local showElementArray = nil -- { true, false, false }
local javascriptAfterSwitch = "";
prefsToggleButton(subpage_active, {
field = "toggle_interface_traffic_rrd_creation",
default = "1",
pref = "interface_rrd_creation",
to_switch = {"row_interfaces_ndpi_timeseries_creation"},
})
local showElement = ntop.getPref("ntopng.prefs.interface_rrd_creation") == "1"
retVal = multipleTableButtonPrefs(subpage_active.entries["toggle_ndpi_timeseries_creation"].title,
subpage_active.entries["toggle_ndpi_timeseries_creation"].description,
l7_rrd_labels, l7_rrd_values,
"per_protocol",
"primary",
"interfaces_ndpi_timeseries_creation",
"ntopng.prefs.interface_ndpi_timeseries_creation", nil,
elementToSwitch, showElementArray, javascriptAfterSwitch, showElement)
print('<tr><th colspan=2 class="info">'..i18n('prefs.local_hosts_timeseries')..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_local_hosts_traffic_rrd_creation",
default = "1",
pref = "host_rrd_creation",
to_switch = {"row_hosts_ndpi_timeseries_creation"},
})
local showElement = ntop.getPref("ntopng.prefs.host_rrd_creation") == "1"
retVal = multipleTableButtonPrefs(subpage_active.entries["toggle_ndpi_timeseries_creation"].title,
subpage_active.entries["toggle_ndpi_timeseries_creation"].description,
l7_rrd_labels, l7_rrd_values,
"none",
"primary",
"hosts_ndpi_timeseries_creation",
"ntopng.prefs.host_ndpi_timeseries_creation", nil,
elementToSwitch, showElementArray, javascriptAfterSwitch, showElement)
print('<tr><th colspan=2 class="info">'..i18n('prefs.l2_devices_timeseries')..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_l2_devices_traffic_rrd_creation",
default = "0",
pref = "l2_device_rrd_creation",
to_switch = {"row_l2_devices_ndpi_timeseries_creation"},
})
local l7_rrd_labels = {i18n("prefs.none"),
i18n("prefs.per_category")}
local l7_rrd_values = {"none",
"per_category"}
local showElement = ntop.getPref("ntopng.prefs.l2_device_rrd_creation") == "1"
retVal = multipleTableButtonPrefs(subpage_active.entries["toggle_ndpi_timeseries_creation"].title,
subpage_active.entries["toggle_ndpi_timeseries_creation"].description,
l7_rrd_labels, l7_rrd_values,
"none",
"primary",
"l2_devices_ndpi_timeseries_creation",
"ntopng.prefs.l2_device_ndpi_timeseries_creation", nil,
elementToSwitch, showElementArray, javascriptAfterSwitch, showElement)
print('<tr><th colspan=2 class="info">'..i18n('prefs.system_probes_timeseries')..'</th></tr>')
prefsToggleButton(subpage_active, {
field = "toggle_system_probes_timeseries",
default = "1",
pref = "system_probes_timeseries",
})
print('<tr><th colspan=2 class="info">'..i18n('prefs.other_timeseries')..'</th></tr>')
if ntop.isPro() then
prefsToggleButton(subpage_active, {
field = "toggle_flow_rrds",
default = "0",
pref = "flow_device_port_rrd_creation",
disabled = not info["version.enterprise_edition"],
})
prefsToggleButton(subpage_active, {
field = "toggle_pools_rrds",
default = "0",
pref = "host_pools_rrd_creation",
})
end
prefsToggleButton(subpage_active, {
field = "toggle_tcp_flags_rrds",
default = "0",
pref = "tcp_flags_rrd_creation",
})
prefsToggleButton(subpage_active, {
field = "toggle_tcp_retr_ooo_lost_rrds",
default = "0",
pref = "tcp_retr_ooo_lost_rrd_creation",
})
prefsToggleButton(subpage_active, {
field = "toggle_vlan_rrds",
default = "0",
pref = "vlan_rrd_creation",
})
prefsToggleButton(subpage_active, {
field = "toggle_asn_rrds",
default = "0",
pref = "asn_rrd_creation",
})
prefsToggleButton(subpage_active, {
field = "toggle_country_rrds",
default = "0",
pref = "country_rrd_creation",
})
if ntop.isPro() then
prefsToggleButton(subpage_active, {
field = "toggle_ndpi_flows_rrds",
default = "0",
pref = "ndpi_flows_rrd_creation",
})
end
if info["version.enterprise_edition"] then
prefsInformativeField("SNMP", i18n("prefs.snmp_timeseries_config_link", {url="?tab=snmp"}))
end
print('</table>')
print('<table class="table">')
if show_advanced_prefs and false --[[ hide these settings for now ]] then
print('<tr><th colspan=2 class="info">Network Interface Timeseries</th></tr>')
prefsInputFieldPrefs("Days for raw stats", "Number of days for which raw stats are kept. Default: 1.", "ntopng.prefs.", "intf_rrd_raw_days", prefs.intf_rrd_raw_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
prefsInputFieldPrefs("Days for 1 min resolution stats", "Number of days for which stats are kept in 1 min resolution. Default: 30.", "ntopng.prefs.", "intf_rrd_1min_days", prefs.intf_rrd_1min_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
prefsInputFieldPrefs("Days for 1 hour resolution stats", "Number of days for which stats are kept in 1 hour resolution. Default: 100.", "ntopng.prefs.", "intf_rrd_1h_days", prefs.intf_rrd_1h_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
prefsInputFieldPrefs("Days for 1 day resolution stats", "Number of days for which stats are kept in 1 day resolution. Default: 365.", "ntopng.prefs.", "intf_rrd_1d_days", prefs.intf_rrd_1d_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
print('<tr><th colspan=2 class="info">Protocol/Networks Timeseries</th></tr>')
prefsInputFieldPrefs("Days for raw stats", "Number of days for which raw stats are kept. Default: 1.", "ntopng.prefs.", "other_rrd_raw_days", prefs.other_rrd_raw_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
--prefsInputFieldPrefs("Days for 1 min resolution stats", "Number of days for which stats are kept in 1 min resolution. Default: 30.", "ntopng.prefs.", "other_rrd_1min_days", prefs.other_rrd_1min_days)
prefsInputFieldPrefs("Days for 1 hour resolution stats", "Number of days for which stats are kept in 1 hour resolution. Default: 100.", "ntopng.prefs.", "other_rrd_1h_days", prefs.other_rrd_1h_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
prefsInputFieldPrefs("Days for 1 day resolution stats", "Number of days for which stats are kept in 1 day resolution. Default: 365.", "ntopng.prefs.", "other_rrd_1d_days", prefs.other_rrd_1d_days, "number", nil, nil, nil, {min=1, max=365*5, --[[ TODO check min/max ]]})
end
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print('</table>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form> ]]
end
-- ================================================================================
function printLogging()
if prefs.has_cmdl_trace_lvl then return end
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.logging")..'</th></tr>')
loggingSelector(subpage_active.entries["toggle_logging_level"].title,
subpage_active.entries["toggle_logging_level"].description,
"toggle_logging_level", "ntopng.prefs.logging_level")
prefsToggleButton(subpage_active, {
field = "toggle_log_to_file",
default = "0",
pref = "log_to_file",
})
prefsToggleButton(subpage_active, {
field = "toggle_access_log",
default = "0",
pref = "enable_access_log",
})
prefsToggleButton(subpage_active, {
field = "toggle_host_pools_log",
default = "0",
pref = "enable_host_pools_log",
})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>
</table>]]
end
function printSnmp()
if not ntop.isPro() then return end
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">SNMP</th></tr>')
local disabled = not info["version.enterprise_edition"]
prefsToggleButton(subpage_active, {
field = "toggle_snmp_rrds",
default = "0",
pref = "snmp_devices_rrd_creation",
disabled = disabled,
})
local t_labels = {"v1", "v2c"}
local t_values = {"0", "1"}
multipleTableButtonPrefs(subpage_active.entries["default_snmp_proto_version"].title, subpage_active.entries["default_snmp_proto_version"].description,
t_labels, t_values, "0", "primary", "default_snmp_version", "ntopng.prefs.default_snmp_version", disabled)
prefsInputFieldPrefs(subpage_active.entries["default_snmp_community"].title, subpage_active.entries["default_snmp_community"].description,
"ntopng.prefs.",
"default_snmp_community",
"public", false, nil, nil, nil, {attributes={spellcheck="false", maxlength=64}, disabled=disabled})
prefsToggleButton(subpage_active, {
field = "toggle_snmp_alerts_port_status_change",
default = "1",
pref = "alerts.snmp_port_status_change",
disabled = disabled,
})
prefsToggleButton(subpage_active, {
field = "toggle_snmp_alerts_port_duplexstatus_change",
default = "1",
pref = "alerts.snmp_port_duplexstatus_change",
disabled = disabled,
})
prefsToggleButton(subpage_active, {
field = "toggle_snmp_alerts_port_errors",
default = "1",
pref = "alerts.snmp_port_errors",
disabled = disabled,
})
prefsInputFieldPrefs(subpage_active.entries["snmp_port_load_threshold"].title,
subpage_active.entries["snmp_port_load_threshold"].description,
"ntopng.prefs.alerts.",
"snmp_port_load_threshold",
"100", "number", nil, false, nil, {min=0, disabled=disabled})
if(disabled) then
prefsInformativeField(i18n("notes"), i18n("enterpriseOnly"))
end
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>
</table>]]
end
function printFlowDBDump()
print('<form method="post">')
print('<table class="table">')
print('<tr><th colspan=2 class="info">'..i18n("prefs.tiny_flows")..'</th></tr>')
local tiny_to_switch = {"max_num_packets_per_tiny_flow", "max_num_bytes_per_tiny_flow"}
prefsToggleButton(subpage_active, {
field = "toggle_flow_db_dump_export",
default = "1",
pref = "tiny_flows_export_enabled",
})
prefsInputFieldPrefs(subpage_active.entries["max_num_packets_per_tiny_flow"].title, subpage_active.entries["max_num_packets_per_tiny_flow"].description,
"ntopng.prefs.", "max_num_packets_per_tiny_flow", prefs.max_num_packets_per_tiny_flow, "number",
true, false, nil, {min=1, max=2^32-1})
prefsInputFieldPrefs(subpage_active.entries["max_num_bytes_per_tiny_flow"].title, subpage_active.entries["max_num_bytes_per_tiny_flow"].description,
"ntopng.prefs.", "max_num_bytes_per_tiny_flow", prefs.max_num_bytes_per_tiny_flow, "number",
true, false, nil, {min=1, max=2^32-1})
print('<tr><th colspan=2 class="info">'..i18n("prefs.aggregated_flows")..'</th></tr>')
local dump_to_switch = {"max_num_aggregated_flows_per_export"}
prefsToggleButton(subpage_active, {
field = "toggle_aggregated_flows_export_limit",
default = "0",
pref = "aggregated_flows_export_limit_enabled",
to_switch = dump_to_switch,
})
local showElement = ntop.getPref("ntopng.prefs.aggregated_flows_export_limit_enabled") == "1"
prefsInputFieldPrefs(subpage_active.entries["max_num_aggregated_flows_per_export"].title,
subpage_active.entries["max_num_aggregated_flows_per_export"].description,
"ntopng.prefs.", "max_num_aggregated_flows_per_export",
prefs.max_num_aggregated_flows_per_export, "number", showElement, false, nil,
{min = 1000, max = 2^32-1})
print('<tr><th colspan=2 style="text-align:right;"><button type="submit" class="btn btn-primary" style="width:115px" disabled="disabled">'..i18n("save")..'</button></th></tr>')
print [[<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
</form>
</table>]]
end
print[[
<table class="table table-bordered">
<col width="20%">
<col width="80%">
<tr><td style="padding-right: 20px;">]]
print(
template.gen("typeahead_input.html", {
typeahead={
base_id = "prefs_search",
action = ntop.getHttpPrefix() .. "/lua/admin/prefs.lua",
json_key = "tab",
query_field = "tab",
query_url = ntop.getHttpPrefix() .. "/lua/find_prefs.lua",
query_title = i18n("prefs.search_preferences"),
style = "width:20em; margin:auto; margin-top: 0.4em; margin-bottom: 1.5em;",
}
})
)
print[[
<div class="list-group">]]
printMenuSubpages(tab)
print[[
</div>
<br>
<div align="center">
<div id="prefs_toggle" class="btn-group">
<form method="post">
<input name="csrf" type="hidden" value="]] print(ntop.getRandomCSRFValue()) print [[" />
<input type=hidden name="show_advanced_prefs" value="]]if show_advanced_prefs then print("false") else print("true") end print[["/>
<br>
<div class="btn-group btn-toggle">
]]
local cls_on = "btn btn-sm"
local onclick_on = ""
local cls_off = cls_on
local onclick_off = onclick_on
if show_advanced_prefs then
cls_on = cls_on..' btn-primary active'
cls_off = cls_off..' btn-default'
onclick_off = "this.form.submit();"
else
cls_on = cls_on..' btn-default'
cls_off = cls_off..' btn-primary active'
onclick_on = "this.form.submit();"
end
print('<button type="button" class="'..cls_on..'" onclick="'..onclick_on..'">'..i18n("prefs.expert_view")..'</button>')
print('<button type="button" class="'..cls_off..'" onclick="'..onclick_off..'">'..i18n("prefs.simple_view")..'</button>')
print[[
</div>
</form>
</div>
</div>
</td><td colspan=2 style="padding-left: 14px;border-left-style: groove; border-width:1px; border-color: #e0e0e0;">]]
if(tab == "report") then
printReportVisualization()
end
if(tab == "in_memory") then
printInMemory()
end
if(tab == "on_disk_ts") then
printStatsTimeseries()
end
if(tab == "alerts") then
printAlerts()
end
if(tab == "ext_alerts") then
printExternalAlertsReport()
end
if(tab == "protocols") then
printProtocolPrefs()
end
if(tab == "discovery") then
printNetworkDiscovery()
end
if(tab == "telemetry") then
printTelemetry()
end
if(tab == "recording") then
printRecording()
end
if(tab == "remote_assistance") then
printRemoteAssitance()
end
if(tab == "retention") then
printDataRetention()
end
if(tab == "misc") then
printMisc()
end
if(tab == "auth") then
printAuthentication()
end
if(tab == "ifaces") then
printInterfaces()
end
if(tab == "logging") then
printLogging()
end
if(tab == "snmp") then
printSnmp()
end
if(tab == "flow_db_dump") then
printFlowDBDump()
end
print[[
</td></tr>
</table>
]]
dofile(dirs.installdir .. "/scripts/lua/inc/footer.lua")
print([[<script>
aysHandleForm("form", {
disable_on_dirty: '.disable-on-dirty',
});
/* Use the validator plugin to override default chrome bubble, which is displayed out of window */
$("form[id!='search-host-form']").validator({disable:true});
</script>]])
local high_res_secs = tonumber(_POST["ts_high_resolution"])
if high_res_secs then
-- update ts_write_slots
local driver = ntop.getPref("ntopng.prefs.timeseries_driver")
local new_slots = 0
local new_steps = 0
-- high_res_secs must be <= 60 to be considered high-resolution
-- the only other option is 300 seconds (5 minutes) and there's
-- no need to use timeseries rings
if driver == "influxdb" and high_res_secs <= 60 then
new_slots = 60 / high_res_secs
new_steps = 60 / new_slots / 5 -- TODO: remove this hardcoded 5
-- important: add one extra slots to give "buffer" time to the writer
new_slots = new_slots + 1
end
-- When high resolution timeseries are enabled, the ntopng C core creates
-- timeseries rings with diffent slots. Each slot holds a snapshot of the
-- host/interface timeseries in a given time interval. For example, if 10s
-- resolution is choose, each slot holds a snapshot representing an interval
-- of 10s. Periodically (in NetworkInterface::periodicStatsUpdate) the slots
-- are polulated and then in minute.lua they are read and exported.
--
-- This Redis preferences tell the C core how to configure the ring:
-- - ntopng.prefs.ts_write_slots: the number of slots to allocate in the ring
-- - ntopng.prefs.ts_write_steps: how many ticks of NetworkInterface::periodicStatsUpdate
-- are necessary to fill a slot.
--
-- For the example above of 10s resolution:
-- - ntopng.prefs.ts_write_slots = 60 / 10 = 6 slots, + 1 extra slot as buffer (see above) = 7
-- - ntopng.prefs.ts_write_steps = 60 / 6 slots = 10s / 5 (5s is the periodicStatsUpdate interval) = 2
--
-- See TimseriesRing.cpp for more details.
--
ntop.setPref("ntopng.prefs.ts_write_slots", tostring(math.ceil(new_slots)))
ntop.setPref("ntopng.prefs.ts_write_steps", tostring(math.ceil(new_steps)))
-- tprint(ntop.getPref("ntopng.prefs.ts_write_slots"))
-- tprint(ntop.getPref("ntopng.prefs.ts_write_steps"))
end
if(_SERVER["REQUEST_METHOD"] == "POST") then
-- Something has changed
ntop.reloadPreferences()
end
end --[[ haveAdminPrivileges ]]