Merge branch 'ntop:dev' into dev

This commit is contained in:
Vasilis Tako 2021-06-18 16:56:19 +02:00 committed by GitHub
commit 661faf5036
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
97 changed files with 609 additions and 760 deletions

View file

@ -0,0 +1,65 @@
--
-- (C) 2019-21 - ntop.org
--
-- ##############################################
local other_alert_keys = require "other_alert_keys"
local classes = require "classes"
local alert = require "alert"
-- ##############################################
local alert_behavior_anomaly = classes.class(alert)
local i18n_title = i18n("alerts_dashboard.alert_unexpected_behavior_title", {type = ""})
-- ##############################################
alert_behavior_anomaly.meta = {
alert_key = other_alert_keys.alert_behavior_anomaly,
i18n_title = i18n_title,
icon = "fas fa-fw fa-exclamation",
}
-- ##############################################
-- @brief Prepare an alert table used to generate the alert
-- @param value The value got from the measurement
-- @param lower_bound The lower bound of the measurement
-- @param upper_bound The upper bound of the measurement
-- @return A table with the alert built
function alert_behavior_anomaly:init(entity, type_of_behaviour, value, upper_bound, lower_bound)
-- Call the parent constructor
self.super:init()
self.alert_type_params = {
entity = entity,
type_of_behaviour = type_of_behaviour,
value = value,
upper_bound = upper_bound,
lower_bound = lower_bound,
}
end
-- #######################################################
-- @brief Format an alert into a human-readable string
-- @param ifid The integer interface id of the generated alert
-- @param alert The alert description table, including alert data such as the generating entity, timestamp, granularity, type
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_behavior_anomaly.format(ifid, alert, alert_type_params)
return(i18n("alerts_dashboard.unexpected_behavior_anomaly_description",
{
entity = alert_type_params.entity,
type_of_behaviour = alert_type_params.type_of_behaviour,
value = alert_type_params.value,
lower_bound = alert_type_params.lower_bound or 0,
upper_bound = alert_type_params.upper_bound or 0,
}))
end
-- #######################################################
return alert_behavior_anomaly

View file

@ -40,30 +40,22 @@ end
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function alert_lateral_movement.format(ifid, alert, alert_type_params)
local vlan_id = tonumber(alert.vlan_id) or 0
local client = {host = alert.cli_ip, vlan = vlan_id}
local server = {host = alert.srv_ip, vlan = vlan_id}
-- Extracting info field
local info = ""
local href = ""
if alert.json then
info = json.decode(alert["json"])
if info["info"] then
info = info["info"]
if not isEmptyString(info["info"]) then
info = "[" .. info["info"] .. "]"
else
info = ""
end
end
local rsp = hostinfo2detailshref(client, nil, hostinfo2label(client))..
" <i class=\"fas fa-fw fa-exchange-alt fa-lg\" aria-hidden=\"true\" data-original-title=\"\" title=\"\"></i> " ..
hostinfo2detailshref(server, nil, hostinfo2label(server))
href = '<a href="/lua/pro/enterprise/service_map.lua"><i class="fas fa-lg fa-concierge-bell"></i></a>'
rsp = rsp .. " ["..interface.getnDPIProtoName(alert.l7_proto).."]"
if not isEmptyString(info) then
rsp = rsp .. "[" .. info .. "]"
end
return(rsp)
return(i18n("alerts_dashboard.lateral_movement_descr", { info = info, href = href }))
end
-- #######################################################

View file

@ -46,28 +46,24 @@ end
-- @param alert_type_params Table `alert_type_params` as built in the `:init` method
-- @return A human-readable string
function host_alert_flow_anomaly.format(ifid, alert, alert_type_params)
local alert_consts = require("alert_consts")
local json = json.decode(alert.json)
local is_both = alert_type_params["is_both"]
local is_client_alert = alert_type_params["is_client_alert"]
local role
local host = alert_consts.formatHostAlert(ifid, alert["ip"], alert["vlan_id"])
local is_both = alert_type_params["is_both"]
local is_client_alert = alert_type_params["is_client_alert"]
local role
if(is_both) then
role = "client and server"
elseif(is_client_alert) then
role = "client"
else
role = "server"
end
if(is_both) then
role = i18n("client_and_server")
elseif(is_client_alert) then
role = i18n("client")
else
role = i18n("server")
end
return i18n("alert_messages.flow_number_anomaly", {
role = role,
host = host,
value = alert_type_params["value"],
lower_bound = alert_type_params["lower_bound"],
upper_bound = alert_type_params["upper_bound"],
})
return i18n("alert_messages.flow_number_anomaly", {
role = role,
value = alert_type_params["value"],
lower_bound = alert_type_params["lower_bound"],
upper_bound = alert_type_params["upper_bound"],
})
end
-- #######################################################

View file

@ -81,18 +81,13 @@ function host_alert_score_anomaly.format(ifid, alert, alert_type_params)
local is_both = alert_type_params["is_both"]
local role
local host = alert_consts.formatHostAlert(ifid, alert["ip"], alert["vlan_id"])
local sec_cat = 0
local net_cat = 0
if(is_both) then
role = i18n("client_and_server")
net_cat, sec_cat = get_problematic_category(alert_type_params, true)
elseif(is_client_alert) then
role = i18n("client")
net_cat, sec_cat = get_problematic_category(alert_type_params, nil, "client")
else
role = i18n("server")
net_cat, sec_cat = get_problematic_category(alert_type_params, nil, "server")
end
return i18n("alert_messages.score_number_anomaly", {
@ -101,8 +96,6 @@ function host_alert_score_anomaly.format(ifid, alert, alert_type_params)
score = alert_type_params["value"],
lower_bound = alert_type_params["lower_bound"],
upper_bound = alert_type_params["upper_bound"],
network = net_cat,
security = sec_cat,
})
end

View file

@ -316,6 +316,22 @@ end
-- ##############################################
-- @brief Import a previously `export`ed exclusions configuration
function alert_exclusions.import(exclusions)
_set_configured_alert_exclusions(exclusions)
end
-- ##############################################
-- @brief Exports the current configuration
function alert_exclusions.export()
local exclusions = _get_configured_alert_exclusions()
return exclusions
end
-- ##############################################
-- @brief Delete all alert_exclusions
function alert_exclusions.cleanup()
local locked = _lock()

View file

@ -777,4 +777,28 @@ function alert_utils.notify_ntopng_stop()
return(notify_ntopng_status(false))
end
function alert_utils.formatBehaviorAlert(params, anomalies, stats, id, subtype)
-- Cycle throught the behavior stats
for anomaly_type, anomaly in pairs(anomalies) do
local alert = alert_consts.alert_types.alert_behavior_anomaly.new(
i18n(subtype .. "_id", {id = id}),
i18n("alert_behaviors." .. anomaly_type),
stats[anomaly_type]["value"],
stats[anomaly_type]["lower_bound"],
stats[anomaly_type]["upper_bound"]
)
alert:set_score_warning()
alert:set_granularity(params.granularity)
alert:set_subtype(subtype .. "_" .. id)
-- Trigger an alert if an anomaly is found
if anomaly == true then
alert:trigger(params.alert_entity, nil, params.cur_alerts)
else
alert:release(params.alert_entity, nil, params.cur_alerts)
end
end
end
return alert_utils

View file

@ -8,28 +8,29 @@ require "lua_utils"
local import_export = require "import_export"
local json = require "dkjson"
local checks = require "checks"
local alert_exclusions = require "alert_exclusions"
local rest_utils = require "rest_utils"
-- ##############################################
local scripts_import_export = {}
local checks_import_export = {}
-- ##############################################
function scripts_import_export:create(args)
function checks_import_export:create(args)
-- Instance of the base class
local _scripts_import_export = import_export:create()
local _checks_import_export = import_export:create()
-- Subclass using the base class instance
self.key = "scripts"
-- self is passed as argument so it will be set as base class metatable
-- and this will actually make it possible to override functions
local _scripts_import_export_instance = _scripts_import_export:create(self)
local _checks_import_export_instance = _checks_import_export:create(self)
-- Compute
-- Return the instance
return _scripts_import_export_instance
return _checks_import_export_instance
end
-- ##############################################
@ -37,7 +38,7 @@ end
-- @brief Import configuration
-- @param conf The configuration to be imported
-- @return A table with a key "success" set to true is returned on success. A key "err" is set in case of failure, with one of the errors defined in rest_utils.consts.err.
function scripts_import_export:import(conf)
function checks_import_export:import(conf)
local res = {}
if table.empty(conf) then
@ -45,7 +46,7 @@ function scripts_import_export:import(conf)
return res
end
local config_set = conf["0"]
local config_set = conf[tostring(checks.DEFAULT_CONFIGSET_ID)]
if config_set == nil then
res.err = rest_utils.consts.err.bad_content
@ -62,6 +63,12 @@ function scripts_import_export:import(conf)
end
if not res.err then
-- Import exclusions (if present)
if conf["alert_exclusions"] then
alert_exclusions.import(conf["alert_exclusions"])
end
res.success = true
end
@ -72,10 +79,11 @@ end
-- @brief Export configuration
-- @return The current configuration
function scripts_import_export:export()
function checks_import_export:export()
local conf = {}
conf[checks.DEFAULT_CONFIGSET_ID] = checks.getConfigset()
conf["alert_exclusions"] = alert_exclusions.export()
return conf
end
@ -83,10 +91,10 @@ end
-- ##############################################
-- @brief Reset configuration
function scripts_import_export:reset()
function checks_import_export:reset()
checks.resetConfigset()
end
-- ##############################################
return scripts_import_export
return checks_import_export