From 23b412ea3ce78ea98953b813efd28cb30d48d6a8 Mon Sep 17 00:00:00 2001 From: Melissa Kilby Date: Wed, 19 Jun 2024 05:58:28 +0000 Subject: [PATCH] new(metrics): add host_ifinfo metric Signed-off-by: Melissa Kilby --- unit_tests/engine/test_falco_utils.cpp | 25 ++++++++++++++++ userspace/engine/falco_utils.cpp | 32 +++++++++++++++++++++ userspace/engine/falco_utils.h | 10 +++++++ userspace/falco/falco_metrics.cpp | 39 +++++++++++++++++++++++++ userspace/falco/stats_writer.cpp | 40 ++++++++++++++++++++++++++ 5 files changed, 146 insertions(+) diff --git a/unit_tests/engine/test_falco_utils.cpp b/unit_tests/engine/test_falco_utils.cpp index 9f9a56c0..07f9dc3c 100644 --- a/unit_tests/engine/test_falco_utils.cpp +++ b/unit_tests/engine/test_falco_utils.cpp @@ -101,3 +101,28 @@ TEST(FalcoUtils, matches_wildcard) ASSERT_FALSE(falco::utils::matches_wildcard("*hello*world", "come on hello this world yes")); ASSERT_FALSE(falco::utils::matches_wildcard("*hello*world*", "come on hello this yes")); } + +#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__) +TEST(FalcoUtils, ipv4addr_to_string) +{ + ASSERT_EQ(falco::utils::network::ipv4addr_to_string(0x0101A8C0), "192.168.1.1"); + ASSERT_EQ(falco::utils::network::ipv4addr_to_string(0x0100007F), "127.0.0.1"); + ASSERT_EQ(falco::utils::network::ipv4addr_to_string(0xFFFFFFFF), "255.255.255.255"); + ASSERT_EQ(falco::utils::network::ipv4addr_to_string(0x00000000), "0.0.0.0"); +} + +TEST(FalcoUtils, ipv6addr_to_string) +{ + ipv6addr addr1("2001:0db8:85a3:0000:0000:8a2e:0370:7334"); + ASSERT_EQ(falco::utils::network::ipv6addr_to_string(addr1), "2001:db8:85a3:0:0:8a2e:370:7334"); + + ipv6addr addr2("fe80:0:0:0:2aa:ff:fe9a:4ca3"); + ASSERT_EQ(falco::utils::network::ipv6addr_to_string(addr2), "fe80:0:0:0:2aa:ff:fe9a:4ca3"); + + ipv6addr addr3("0:0:0:0:0:0:0:0"); + ASSERT_EQ(falco::utils::network::ipv6addr_to_string(addr3), "0:0:0:0:0:0:0:0"); + + ipv6addr addr4("ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); + ASSERT_EQ(falco::utils::network::ipv6addr_to_string(addr4), "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff"); +} +#endif diff --git a/userspace/engine/falco_utils.cpp b/userspace/engine/falco_utils.cpp index 17259513..a3a83c5a 100644 --- a/userspace/engine/falco_utils.cpp +++ b/userspace/engine/falco_utils.cpp @@ -257,6 +257,38 @@ bool is_unix_scheme(const std::string& url) { return sinsp_utils::startswith(url, UNIX_SCHEME); } + +#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__) +std::string ipv4addr_to_string(uint32_t addr) +{ + char dest[16]; + snprintf( + dest, + sizeof(dest), + "%d.%d.%d.%d", + (addr & 0xFF), + ((addr & 0xFF00) >> 8), + ((addr & 0xFF0000) >> 16), + ((addr & 0xFF000000) >> 24)); + return std::string(dest); +} + +std::string ipv6addr_to_string(const ipv6addr& addr) +{ + std::ostringstream oss; + const uint16_t* words = reinterpret_cast(addr.m_b); + for (int i = 0; i < 8; ++i) + { + if (i != 0) + { + oss << ':'; + } + oss << std::hex << ntohs(words[i]); + } + return oss.str(); +} +#endif + } // namespace network } // namespace utils } // namespace falco diff --git a/userspace/engine/falco_utils.h b/userspace/engine/falco_utils.h index 21234991..94e50e89 100644 --- a/userspace/engine/falco_utils.h +++ b/userspace/engine/falco_utils.h @@ -22,6 +22,10 @@ limitations under the License. #include #include +#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__) +#include +#include +#endif namespace falco::utils { @@ -45,5 +49,11 @@ namespace network { static const std::string UNIX_SCHEME("unix://"); bool is_unix_scheme(const std::string& url); +#if defined(__linux__) and !defined(MINIMAL_BUILD) and !defined(__EMSCRIPTEN__) +// todo: consider extending libs and expose API for ipv4 and ipv6 to string conversion +std::string ipv4addr_to_string(uint32_t addr); +std::string ipv6addr_to_string(const ipv6addr& addr); +#endif + } // namespace network } // namespace falco::utils diff --git a/userspace/falco/falco_metrics.cpp b/userspace/falco/falco_metrics.cpp index 103f18c9..9422715e 100644 --- a/userspace/falco/falco_metrics.cpp +++ b/userspace/falco/falco_metrics.cpp @@ -108,6 +108,45 @@ std::string falco_metrics::to_text(const falco::app::state& state) fs::path fs_path = item.first; prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus("falco_sha256_config_files", "falcosecurity", "falco", {{"file_name", fs_path.filename().stem()}, {"sha256", item.second}}); } + + static bool is_first_call = true; + static std::string ifinfo_json_escaped; + if (is_first_call) + { + is_first_call = false; + auto ipv4list = inspector->get_ifaddr_list().get_ipv4_list(); + auto ipv6list = inspector->get_ifaddr_list().get_ipv6_list(); + nlohmann::json ipv4_json; + nlohmann::json ipv6_json; + if(ipv4list) + { + for (const auto& item : *ipv4list) + { + if(item.m_name == "lo") + { + continue; + } + ipv4_json[item.m_name] = falco::utils::network::ipv4addr_to_string(item.m_addr); + } + } + + if(ipv6list) + { + for (const auto& item : *ipv6list) + { + if(item.m_name == "lo") + { + continue; + } + ipv6_json[item.m_name] = falco::utils::network::ipv6addr_to_string(item.m_net); + } + } + nlohmann::json ifinfo_json; + ifinfo_json["ipv4"] = ipv4_json; + ifinfo_json["ipv6"] = ipv6_json; + ifinfo_json_escaped = ifinfo_json.dump(); + } + prometheus_text += prometheus_metrics_converter.convert_metric_to_text_prometheus("host_ifinfo", "falcosecurity", "falco", {{"host_ifinfo", ifinfo_json_escaped}}); #endif for (const std::string& source: inspector->event_sources()) diff --git a/userspace/falco/stats_writer.cpp b/userspace/falco/stats_writer.cpp index 17fb8bc1..7dfb3a26 100644 --- a/userspace/falco/stats_writer.cpp +++ b/userspace/falco/stats_writer.cpp @@ -357,6 +357,46 @@ void stats_writer::collector::get_metrics_output_fields_wrapper( metric_name_file_sha256 = "falco.sha256_config_file." + falco::utils::sanitize_metric_name(metric_name_file_sha256); output_fields[metric_name_file_sha256] = item.second; } + + static bool is_first_call = true; + static std::string ifinfo_json_escaped; + if (is_first_call) + { + is_first_call = false; + auto ipv4list = inspector->get_ifaddr_list().get_ipv4_list(); + auto ipv6list = inspector->get_ifaddr_list().get_ipv6_list(); + nlohmann::json ipv4_json; + nlohmann::json ipv6_json; + if(ipv4list) + { + for (const auto& item : *ipv4list) + { + if(item.m_name == "lo") + { + continue; + } + ipv4_json[item.m_name] = falco::utils::network::ipv4addr_to_string(item.m_addr); + } + } + + if(ipv6list) + { + for (const auto& item : *ipv6list) + { + if(item.m_name == "lo") + { + continue; + } + ipv6_json[item.m_name] = falco::utils::network::ipv6addr_to_string(item.m_net); + } + } + nlohmann::json ifinfo_json; + ifinfo_json["ipv4"] = ipv4_json; + ifinfo_json["ipv6"] = ipv6_json; + ifinfo_json_escaped = ifinfo_json.dump(); + } + output_fields["falco.host_ifinfo"] = ifinfo_json_escaped; + #endif output_fields["evt.source"] = src; for (size_t i = 0; i < sizeof(all_driver_engines) / sizeof(const char*); i++)