From: Vitalii Tron -X (vtron - SOFTSERVE INC at Cisco) Date: Tue, 5 Mar 2024 17:21:04 +0000 (+0000) Subject: Pull request #4230: trace: Add tenants filtering and logging X-Git-Tag: 3.1.82.0~6 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=dc7c1d21affb67d417eec0c6e0bf62c7df4eef8f;p=thirdparty%2Fsnort3.git Pull request #4230: trace: Add tenants filtering and logging Merge in SNORT/snort3 from ~VTRON/snort3:trace_module_tenant to master Squashed commit of the following: commit ae746511828751a36b744c3056da353cdfecf00e Author: Vitalii Tron Date: Tue Feb 27 11:38:40 2024 -0500 trace: add tenants logging --- diff --git a/src/framework/dev_notes.txt b/src/framework/dev_notes.txt index 7fd55e68c..bb733cc82 100644 --- a/src/framework/dev_notes.txt +++ b/src/framework/dev_notes.txt @@ -10,6 +10,6 @@ attached to configuration with one element per packet thread, however those cases are rare and should only be needed by the framework code, not the plugins. -PacketConstraints allow you to match packets and flows against a 5-tuple. -( ip_proto; src_ip; dst_ip; src_port; dst_port) +PacketConstraints allow you to match packets and flows against a 6-tuple. +( ip_proto; src_ip; dst_ip; src_port; dst_port; tenant) diff --git a/src/framework/packet_constraints.cc b/src/framework/packet_constraints.cc index 939a287d1..67ccdad99 100644 --- a/src/framework/packet_constraints.cc +++ b/src/framework/packet_constraints.cc @@ -40,7 +40,7 @@ inline bool match_constraints(const snort::PacketConstraints& cs, (!(cs.set_bits & SetBits::SRC_IP) or (sip == cs.src_ip)) and (!(cs.set_bits & SetBits::DST_IP) or (dip == cs.dst_ip)); - if (res && tenant_id && !cs.tenants.empty()) + if (res and (cs.set_bits & SetBits::TENANT) and tenant_id and !cs.tenants.empty()) { auto it = std::find_if(cs.tenants.cbegin(), cs.tenants.cend(), [tenant_id](uint32_t t){ return t == tenant_id; }); @@ -87,7 +87,7 @@ bool PacketConstraints::operator==(const PacketConstraints& other) const and ( !(set_bits & DST_PORT) or dst_port == other.dst_port ) and ( !(set_bits & SRC_IP) or src_ip == other.src_ip ) and ( !(set_bits & DST_IP) or dst_ip == other.dst_ip ) - and ( tenants == other.tenants ); + and ( !(set_bits & TENANT) or tenants == other.tenants ); } bool PacketConstraints::packet_match(const Packet& p) const @@ -110,9 +110,10 @@ bool PacketConstraints::packet_match(const Packet& p) const const auto& dip = *p.ptrs.ip_api.get_dst(); const auto sp = p.ptrs.sp; const auto dp = p.ptrs.dp; + const auto tenant = p.pkth->tenant_id; - return match_constraints(*this, sip, dip, sp, dp, p.pkth->tenant_id) or - match_constraints(*this, dip, sip, dp, sp, p.pkth->tenant_id); + return match_constraints(*this, sip, dip, sp, dp, tenant) or + match_constraints(*this, dip, sip, dp, sp, tenant); } bool PacketConstraints::flow_match(const Flow& f) const @@ -181,11 +182,9 @@ TEST_CASE("Packet constraints comparison", "[framework]") const uint32_t ip1 = 0x01010101; const uint32_t ip2 = 0x02020202; PacketConstraints exp = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); - exp.tenants = tenants1; + SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true, tenants1); PacketConstraints act = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, - SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true); - act.tenants = tenants2; + SfIp(&ip1, AF_INET), SfIp(&ip2, AF_INET), (uint8_t)-1, true, tenants2); CHECK( exp == act ); } } @@ -209,6 +208,7 @@ TEST_CASE("Packet constraints matching", "[framework]") cs.set_bits |= PacketConstraints::SetBits::DST_PORT; cs.set_bits |= PacketConstraints::SetBits::SRC_IP; cs.set_bits |= PacketConstraints::SetBits::DST_IP; + cs.set_bits |= PacketConstraints::SetBits::TENANT; cs.ip_proto = proto; cs.src_port = sport; diff --git a/src/framework/packet_constraints.h b/src/framework/packet_constraints.h index ffe6c03bc..093a61ae7 100644 --- a/src/framework/packet_constraints.h +++ b/src/framework/packet_constraints.h @@ -39,13 +39,15 @@ struct PacketConstraints DST_IP = 1 << 2, SRC_PORT = 1 << 3, DST_PORT = 1 << 4, + TENANT = 1 << 5, }; PacketConstraints() = default; PacketConstraints(IpProtocol ip_proto, uint16_t src_port, uint16_t dst_port, - const snort::SfIp& src_ip, const snort::SfIp& dst_ip, uint8_t set_bits, bool match) : + const snort::SfIp& src_ip, const snort::SfIp& dst_ip, uint8_t set_bits, bool match, + const std::vector& tenants = std::vector()) : ip_proto(ip_proto), src_port(src_port), dst_port(dst_port), - src_ip(src_ip), dst_ip(dst_ip), set_bits(set_bits), match(match) + src_ip(src_ip), dst_ip(dst_ip), set_bits(set_bits), match(match), tenants(tenants) {} PacketConstraints(const PacketConstraints&); PacketConstraints& operator=(const PacketConstraints& other); diff --git a/src/network_inspectors/packet_tracer/packet_tracer_module.cc b/src/network_inspectors/packet_tracer/packet_tracer_module.cc index f714aa1b0..df9f43d30 100644 --- a/src/network_inspectors/packet_tracer/packet_tracer_module.cc +++ b/src/network_inspectors/packet_tracer/packet_tracer_module.cc @@ -130,7 +130,10 @@ static int enable(lua_State* L) PacketConstraints constraints = {}; if (tenantsstr) + { StrToIntVector(tenantsstr, ',', constraints.tenants); + constraints.set_bits |= PacketConstraints::SetBits::TENANT; + } if (proto and (IpProtocol)proto < IpProtocol::PROTO_NOT_SET) { diff --git a/src/trace/trace_loggers.cc b/src/trace/trace_loggers.cc index 2025bdeaa..fb4402218 100644 --- a/src/trace/trace_loggers.cc +++ b/src/trace/trace_loggers.cc @@ -60,6 +60,13 @@ static std::string get_ntuple(bool ntuple, const Packet* p) ss << unsigned(p->get_ip_proto_next()) << " "; ss << "AS=" << p->pkth->address_space_id << ":"; + if (p->pkth->tenant_id) + ss << "TN=" << p->pkth->tenant_id<< ":"; + + const auto vni = p->get_flow_geneve_vni(); + if (vni) + ss << "VNI=" << vni<< ":"; + return ss.str(); } diff --git a/src/trace/trace_module.cc b/src/trace/trace_module.cc index ea04a64ef..018b26181 100644 --- a/src/trace/trace_module.cc +++ b/src/trace/trace_module.cc @@ -133,6 +133,9 @@ void TraceModule::generate_params() { "match", Parameter::PT_BOOL, nullptr, "true", "use constraints to filter traces" }, + + { "tenants", Parameter::PT_STRING, nullptr, nullptr, + "tenants filter" }, { nullptr, Parameter::PT_MAX, nullptr, nullptr, nullptr } }; diff --git a/src/trace/trace_parser.cc b/src/trace/trace_parser.cc index 5b132cfe4..8822a4bc4 100644 --- a/src/trace/trace_parser.cc +++ b/src/trace/trace_parser.cc @@ -25,6 +25,7 @@ #include "framework/module.h" #include "managers/module_manager.h" +#include "utils/util.h" #include "trace_config.h" @@ -36,7 +37,7 @@ TraceParser::TraceParser(TraceConfig& tc) : trace_config(tc) { // Will be initialized only once when first TraceParser instance created - if ( s_configured_trace_options.empty() ) + if (s_configured_trace_options.empty()) init_configured_trace_options(); else reset_configured_trace_options(); @@ -44,20 +45,20 @@ TraceParser::TraceParser(TraceConfig& tc) bool TraceParser::set_traces(const std::string& module_name, const Value& val) { - if ( !s_configured_trace_options.count(module_name) - and module_name != DEFAULT_TRACE_OPTION_NAME ) + if (!s_configured_trace_options.count(module_name) + and module_name != DEFAULT_TRACE_OPTION_NAME) return false; - if ( module_name == DEFAULT_TRACE_OPTION_NAME ) + if (module_name == DEFAULT_TRACE_OPTION_NAME) { - for ( const auto& trace_options : s_configured_trace_options ) + for (const auto& trace_options : s_configured_trace_options) { - if ( trace_options.second.at(DEFAULT_TRACE_OPTION_NAME) ) + if (trace_options.second.at(DEFAULT_TRACE_OPTION_NAME)) continue; - for ( const auto& trace_option : trace_options.second ) + for (const auto& trace_option : trace_options.second) { - if ( !trace_option.second ) + if (!trace_option.second) trace_config.set_trace(trace_options.first, trace_option.first, val.get_uint8()); } @@ -65,12 +66,12 @@ bool TraceParser::set_traces(const std::string& module_name, const Value& val) return true; } - else if ( val.is(DEFAULT_TRACE_OPTION_NAME) ) + else if (val.is(DEFAULT_TRACE_OPTION_NAME)) { auto& trace_options = s_configured_trace_options[module_name]; - for ( const auto& trace_option : trace_options ) + for (const auto& trace_option : trace_options) { - if ( !trace_option.second ) + if (!trace_option.second) trace_config.set_trace(module_name, trace_option.first, val.get_uint8()); } trace_options[DEFAULT_TRACE_OPTION_NAME] = true; @@ -87,39 +88,48 @@ bool TraceParser::set_traces(const std::string& module_name, const Value& val) bool TraceParser::set_constraints(const Value& val) { - if ( val.is("ip_proto") ) + if (val.is("ip_proto")) { parsed_constraints.ip_proto = static_cast(val.get_uint8()); parsed_constraints.set_bits |= PacketConstraints::SetBits::IP_PROTO; } - else if ( val.is("src_port") ) + else if (val.is("src_port")) { parsed_constraints.src_port = val.get_uint16(); parsed_constraints.set_bits |= PacketConstraints::SetBits::SRC_PORT; } - else if ( val.is("dst_port") ) + else if (val.is("dst_port")) { parsed_constraints.dst_port = val.get_uint16(); parsed_constraints.set_bits |= PacketConstraints::SetBits::DST_PORT; } - else if ( val.is("src_ip") ) + else if (val.is("src_ip")) { const char* str = val.get_string(); - if ( parsed_constraints.src_ip.set(str) != SFIP_SUCCESS ) + if (parsed_constraints.src_ip.set(str) != SFIP_SUCCESS) return false; parsed_constraints.set_bits |= PacketConstraints::SetBits::SRC_IP; } - else if ( val.is("dst_ip") ) + else if (val.is("dst_ip")) { const char* str = val.get_string(); - if ( parsed_constraints.dst_ip.set(str) != SFIP_SUCCESS ) + if (parsed_constraints.dst_ip.set(str) != SFIP_SUCCESS) return false; parsed_constraints.set_bits |= PacketConstraints::SetBits::DST_IP; } - else if ( val.is("match") ) + else if (val.is("match")) parsed_constraints.match = val.get_bool(); + else if (val.is("tenants")) + { + const char* tenants_str = val.get_string(); + if (!tenants_str) + return false; + + StrToIntVector(tenants_str, ',', parsed_constraints.tenants); + parsed_constraints.set_bits |= PacketConstraints::SetBits::TENANT; + } else return false; @@ -128,7 +138,7 @@ bool TraceParser::set_constraints(const Value& val) void TraceParser::finalize_constraints() { - if ( !parsed_constraints.match or parsed_constraints.set_bits ) + if (!parsed_constraints.match or parsed_constraints.set_bits) trace_config.constraints = new PacketConstraints(parsed_constraints); } @@ -143,9 +153,9 @@ void TraceParser::clear_constraints() void TraceParser::reset_configured_trace_options() { - for ( auto& module_trace_options : s_configured_trace_options ) + for (auto& module_trace_options : s_configured_trace_options) { - for ( auto& trace_options : module_trace_options.second ) + for (auto& trace_options : module_trace_options.second) trace_options.second = false; } } @@ -153,16 +163,16 @@ void TraceParser::reset_configured_trace_options() void TraceParser::init_configured_trace_options() { auto trace_modules = ModuleManager::get_all_modules(); - for ( const auto* module : trace_modules ) + for (const auto* module : trace_modules) { const TraceOption* trace_options = module->get_trace_options(); - if ( !trace_options ) + if (!trace_options) continue; auto& module_trace_options = s_configured_trace_options[module->get_name()]; module_trace_options[DEFAULT_TRACE_OPTION_NAME] = false; - while ( trace_options->name ) + while (trace_options->name) { module_trace_options[trace_options->name] = false; ++trace_options; @@ -195,6 +205,9 @@ void TraceParser::init_configured_trace_options() #define PORT_OPTION(name, value) \ CONFIG_OPTION(name, (uint64_t)value, Parameter::PT_INT, "0:65535") +#define TENANT_OPTION(name, value) \ + CONFIG_OPTION(name, value, Parameter::PT_STRING, nullptr) + enum { OPT_1, OPT_2 }; static const TraceOption s_trace_options[] = @@ -449,6 +462,21 @@ TEST_CASE("packet constraints", "[TraceParser]") CONFIG_OPTION(invalid_option, (uint64_t)5, Parameter::PT_INT, "0:8"); CHECK(false == tp.set_constraints(invalid_option)); } + + SECTION("tenants") + { + TENANT_OPTION(tenants, "11,12"); + const auto expected_tenants = std::vector{ 11, 12 }; + + const PacketConstraints expected_constraints = PacketConstraints(IpProtocol::PROTO_NOT_SET, 0, 0, + SfIp(), SfIp(), PacketConstraints::TENANT, true, expected_tenants); + + CHECK(true == tp.set_constraints(tenants)); + tp.finalize_constraints(); + + REQUIRE(tc.constraints != nullptr); + CHECK(*tc.constraints == expected_constraints); + } } #endif // UNIT_TEST