Add support for 'Is empty' and 'Is not empty' in filters

This commit is contained in:
Alfredo Cardigliano 2025-09-15 14:48:55 +02:00
parent f6285230e3
commit 137eee2dcd
4 changed files with 42 additions and 26 deletions

View file

@ -525,6 +525,8 @@ local lang = {
["ipv4"] = "IPv4",
["ipv6"] = "IPv6",
["is_connected"] = "is connected",
["is_empty"] = "is empty",
["is_not_empty"] = "is not empty",
["issuerDN"] = "IssuerDN",
["issues_score"] = "Score / Issues",
["ja4_client_hash"] = "JA4 Client Hash",

View file

@ -298,6 +298,11 @@ function alert_store:build_sql_cond(cond, is_write)
local real_field = self:get_column_name(cond.field, is_write, cond.value)
-- Special case: description
if cond.field == "description" then
real_field = 'json'
end
local sql_cond
local sql_op = tag_utils.tag_operators[cond.op]
@ -472,9 +477,6 @@ function alert_store:build_sql_cond(cond, is_write)
sql_cond = string.format("%s = 1", self:get_column_name('is_server', is_write))
end
-- Special case: description
elseif cond.field == "description" then
sql_cond = string.format("json LIKE %s", string.format("'%%%s%%'", cond.value))
-- Number
elseif cond.value_type == 'number' then
if cond.op == 'in' then
@ -499,6 +501,10 @@ function alert_store:build_sql_cond(cond, is_write)
sql_cond = real_field .. ' LIKE ' .. string.format("'%%%s%%'", cond.value)
elseif cond.op == 'nin' then
sql_cond = real_field .. ' NOT LIKE ' .. string.format("'%%%s%%'", cond.value)
elseif cond.op == 'empty' then
sql_cond = real_field .. ' = ' .. "''"
elseif cond.op == 'nempty' then
sql_cond = real_field .. ' <> ' .. "''"
else
-- Any other operator
sql_cond = string.format("%s %s ('%s')", real_field, sql_op, cond.value)
@ -2143,6 +2149,7 @@ function alert_store:add_request_filters(is_write)
self:add_filter_condition_list('score', score, 'number')
self:add_filter_condition_list('tstamp', tstamp, 'number')
self:add_filter_condition_list('info', info, 'string')
self:add_filter_condition_list('description', description)
if (ntop.isClickHouseEnabled()) then

View file

@ -40,7 +40,9 @@ tag_utils.tag_operators = {
["gte"] = ">=",
["lte"] = "<=",
["in"] = i18n("has"),
["nin"] = i18n("does_not_have")
["nin"] = i18n("does_not_have"),
["empty"] = i18n("is_empty"),
["nempty"] = i18n("is_not_empty"),
}
-- #####################################
@ -49,7 +51,7 @@ tag_utils.tag_operators = {
tag_utils.input_types = {
input = 'input',
select = 'select',
select_with_input = 'select-with-input'
select_with_input = 'select-with-input',
}
-- #####################################
@ -414,7 +416,7 @@ tag_utils.defined_tags = {
info = {
value_type = 'text',
i18n_label = i18n('db_search.tags.info'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
bytes = {
@ -542,13 +544,13 @@ tag_utils.defined_tags = {
community_id = {
value_type = 'text',
i18n_label = i18n('db_search.tags.community_id'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
cli_fingerprint = {
value_type = 'text',
i18n_label = i18n('db_search.tags.cli_fingerprint'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
--ja4_client = {
@ -579,13 +581,13 @@ tag_utils.defined_tags = {
issuer_dn = {
value_type = 'text',
i18n_label = i18n('db_search.tags.issuer_dn'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
user_agent = {
value_type = 'user_agent',
i18n_label = i18n('db_search.tags.user_agent'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
last_server = {
@ -603,7 +605,7 @@ tag_utils.defined_tags = {
dns_query = {
value_type = 'text',
i18n_label = i18n('db_search.tags.dns_query'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
dns_answer = {
@ -615,37 +617,37 @@ tag_utils.defined_tags = {
mdns_answer = {
value_type = 'text',
i18n_label = i18n('db_search.tags.mdns_answer'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
mdns_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.mdns_name'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
mdns_name_txt = {
value_type = 'text',
i18n_label = i18n('db_search.tags.mdns_name_txt'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
mdns_ssid = {
value_type = 'text',
i18n_label = i18n('db_search.tags.mdns_ssid'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
domain_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.domain_name'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
alert_domain = {
value_type = 'text',
i18n_label = i18n('db_search.tags.dga_domain_name'),
operators = { 'eq', 'neq', 'in', 'nin' },
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' },
hourly_available = false,
},
cli_location = {
@ -672,25 +674,25 @@ tag_utils.defined_tags = {
cli_proc_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.cli_proc_name'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
srv_proc_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.srv_proc_name'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
cli_user_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.cli_user_name'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
srv_user_name = {
value_type = 'text',
i18n_label = i18n('db_search.tags.srv_user_name'),
operators = { 'eq', 'neq' },
operators = { 'eq', 'neq', 'empty', 'nempty' },
hourly_available = false,
},
major_connection_state = {
@ -758,7 +760,7 @@ tag_utils.defined_tags = {
description = {
value_type = 'text',
i18n_label = i18n('db_search.tags.alert_description'),
operators = { 'in' },
operators = { 'in', 'empty', 'nempty' },
hourly_available = false,
},
mitre_tactic = {
@ -794,7 +796,7 @@ tag_utils.defined_tags = {
-- value_type = 'wlan_ssid',
value_type = 'text',
i18n_label = i18n('db_search.tags.wlan_ssid'),
operators = { 'eq', 'neq', 'in', 'nin' }
operators = { 'eq', 'neq', 'in', 'nin', 'empty', 'nempty' }
},
apn_mac = {
value_type = 'mac',