From 50fbc7f5ac5329ba2917407a0b042c4652b7fa27 Mon Sep 17 00:00:00 2001 From: Vaxry Date: Tue, 15 Apr 2025 14:49:29 +0100 Subject: [PATCH] rules: add support for resource excludes --- .gitmodules | 3 +++ CMakeLists.txt | 2 ++ example/config.jsonc | 4 +++- src/config/Config.cpp | 10 ++++++++++ src/config/Config.hpp | 12 ++++++++---- src/core/Handler.cpp | 11 +++++++++-- subprojects/re2 | 1 + 7 files changed, 36 insertions(+), 7 deletions(-) create mode 160000 subprojects/re2 diff --git a/.gitmodules b/.gitmodules index 3c54048..67616d6 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,6 @@ [submodule "subprojects/glaze"] path = subprojects/glaze url = https://github.com/stephenberry/glaze +[submodule "subprojects/re2"] + path = subprojects/re2 + url = https://github.com/google/re2 diff --git a/CMakeLists.txt b/CMakeLists.txt index 826e7af..6e818ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,7 @@ target_include_directories(checkpoint PRIVATE "./subprojects/pistache/include" "./subprojects/glaze/include" + "./subprojects/re2/include" "./subprojects/tinylates/include" "./subprojects/pistache/subprojects/cpp-httplib" "./subprojects/pistache/subprojects/hinnant-date/include" @@ -43,5 +44,6 @@ target_link_libraries(checkpoint PkgConfig::deps pistache fmt + re2 tinylates ) diff --git a/example/config.jsonc b/example/config.jsonc index a90743d..f79b0a4 100644 --- a/example/config.jsonc +++ b/example/config.jsonc @@ -33,7 +33,9 @@ "ip_ranges": [ "127.0.0.1/24", "::1/128" - ] + ], + // if this regex matches the resource requested, this rule will not be applied + "exclude_regex": ".*/commit/.*" } ] } \ No newline at end of file diff --git a/src/config/Config.cpp b/src/config/Config.cpp index d3824c5..a2c83b4 100644 --- a/src/config/Config.cpp +++ b/src/config/Config.cpp @@ -5,6 +5,8 @@ #include "../helpers/FsUtils.hpp" #include "../GlobalState.hpp" +#include "../debug/log.hpp" + static CConfig::eConfigIPAction strToAction(const std::string& s) { // TODO: allow any case I'm lazy it's 1am if (s == "ALLOW" || s == "allow" || s == "Allow") @@ -32,6 +34,14 @@ CConfig::CConfig() { parsed.action = strToAction(ic.action); parsed.difficulty = ic.difficulty; + if (!ic.exclude_regex.empty()) { + parsed.exclude_regex = std::make_unique(ic.exclude_regex); + if (parsed.exclude_regex->error_code() != RE2::NoError) { + Debug::log(CRIT, "Regex \"{}\" failed to parse", ic.exclude_regex); + throw std::runtime_error("Failed to parse regex"); + } + } + for (const auto& ir : ic.ip_ranges) { parsed.ip_ranges.emplace_back(CIPRange(ir)); } diff --git a/src/config/Config.hpp b/src/config/Config.hpp index 9b39286..8d83c42 100644 --- a/src/config/Config.hpp +++ b/src/config/Config.hpp @@ -3,6 +3,8 @@ #include #include +#include + #include "IPRange.hpp" class CConfig { @@ -18,13 +20,15 @@ class CConfig { struct SIPRangeConfig { std::string action = ""; std::vector ip_ranges; - int difficulty = -1; + int difficulty = -1; + std::string exclude_regex = ""; }; struct SIPRangeConfigParsed { - eConfigIPAction action = IP_ACTION_DENY; - std::vector ip_ranges; - int difficulty = -1; + eConfigIPAction action = IP_ACTION_DENY; + std::vector ip_ranges; + int difficulty = -1; + std::unique_ptr exclude_regex; }; struct SConfig { diff --git a/src/core/Handler.cpp b/src/core/Handler.cpp index ec908cc..9e346a5 100644 --- a/src/core/Handler.cpp +++ b/src/core/Handler.cpp @@ -243,6 +243,15 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt } if (matched) { + if (ic.difficulty != -1) + challengeDifficulty = ic.difficulty; + + // if we have an exclude regex and it matches the resource, skip this rule + if (ic.exclude_regex && RE2::FullMatch(req.resource(), *ic.exclude_regex)) { + Debug::log(LOG, " | ip rule matched for {}, but resource is excluded.", REQUEST_IP); + continue; + } + if (ic.action == CConfig::IP_ACTION_ALLOW) { Debug::log(LOG, " | Action: PASS (ip rule matched for {})", REQUEST_IP); proxyPass(req, response); @@ -254,8 +263,6 @@ void CServerHandler::onRequest(const Pistache::Http::Request& req, Pistache::Htt } // if it's challenge then it's default so just set the difficulty if applicable and proceed - if (ic.difficulty != -1) - challengeDifficulty = ic.difficulty; break; } } diff --git a/subprojects/re2 b/subprojects/re2 new file mode 160000 index 0000000..c84a140 --- /dev/null +++ b/subprojects/re2 @@ -0,0 +1 @@ +Subproject commit c84a140c93352cdabbfb547c531be34515b12228