#ifndef __RATE_LIMIT_CONFIG_H__ #define __RATE_LIMIT_CONFIG_H__ #include #include #include #include #include "debug.h" #include "generic_rulebase/rulebase_config.h" #include "generic_rulebase/triggers_config.h" #include "generic_rulebase/match_query.h" #include "generic_rulebase/evaluators/trigger_eval.h" USE_DEBUG_FLAG(D_RATE_LIMIT); enum class RateLimitAction { INACTIVE, ACCORDING_TO_PRACTICE, DETECT, PREVENT, UNKNOWN }; class RateLimitTrigger { public: void load(cereal::JSONInputArchive &ar); const std::string & getTriggerId() const { return id; } private: std::string id; }; class RateLimitRule { public: void load(cereal::JSONInputArchive &ar); void prepare(const std::string &asset_id, int zone_id); operator bool() const { if (uri.empty()) { dbgTrace(D_RATE_LIMIT) << "Recived empty URI in rate-limit rule"; return false; } if (uri.at(0) != '/') { dbgWarning(D_RATE_LIMIT) << "Recived invalid rate-limit URI in rate-limit rule: " << uri << " rate-limit URI must start with /"; return false; } if (limit <= 0) { dbgWarning(D_RATE_LIMIT) << "Recived invalid rate-limit limit in rate-limit rule: " << limit << " rate-limit rule limit must be positive"; return false; } return true; } friend std::ostream & operator<<(std::ostream &os, const RateLimitRule &rule) { os << "Uri: " << rule.uri << ", Rate scope: " << rule.scope << ", Limit: " << rule.limit; return os; } int getRateLimit() const { return limit; } const std::string & getRateLimitZone() const { return limit_req_zone_template_value; } const std::string & getRateLimitReq() const { return limit_req_template_value; } const std::string & getRateLimitUri() const { return uri; } const std::string & getRateLimitScope() const { return scope; } const RateLimitAction & getRateLimitAction() const { return action; } const MatchQuery & getRateLimitMatch() const { return match; } const LogTriggerConf & getRateLimitTrigger() const { return trigger; } const std::vector & getRateLimitTriggers() const { return rate_limit_triggers; } bool isRootLocation() const; bool isMatchAny() const; bool operator==(const RateLimitRule &rhs) { return uri == rhs.uri; } bool operator<(const RateLimitRule &rhs) { return uri < rhs.uri; } bool isExactMatch() const { return exact_match || (!uri.empty() && uri.back() != '/'); } void setExactMatch() { exact_match = true; } void appendSlash() { uri += '/'; } private: std::string uri; std::string scope; std::string limit_req_template_value; std::string limit_req_zone_template_value; std::string cache_size = "5m"; RateLimitAction action = RateLimitAction::ACCORDING_TO_PRACTICE; MatchQuery match = MatchQuery(default_match); std::vector rate_limit_triggers; LogTriggerConf trigger; int limit; bool exact_match = false; static const std::string default_match; }; class RateLimitConfig { public: void load(cereal::JSONInputArchive &ar); void addSiblingRateLimitRules(); void prepare(); const std::vector & getRateLimitRules() const { return rate_limit_rules; } const RateLimitAction & getRateLimitMode() const { return mode; } RateLimitRule generateSiblingRateLimitRule(const RateLimitRule &rule); const LogTriggerConf getRateLimitTrigger(const std::string &nginx_uri) const { const RateLimitRule rule = findLongestMatchingRule(nginx_uri); std::set rate_limit_triggers_set; for (const RateLimitTrigger &rate_limit_trigger : rule.getRateLimitTriggers()) { dbgTrace(D_RATE_LIMIT) << "Adding trigger ID: " << rate_limit_trigger.getTriggerId() << " of rule URI: " << rule.getRateLimitUri() << " to the context set"; rate_limit_triggers_set.insert(rate_limit_trigger.getTriggerId()); } ScopedContext ctx; ctx.registerValue>(TriggerMatcher::ctx_key, rate_limit_triggers_set); return getConfigurationWithDefault(LogTriggerConf(), "rulebase", "log"); } static void setIsActive(bool _is_active) { is_active |= _is_active; } static void resetIsActive() { is_active = false; } static bool isActive() { return is_active; } static const std::map rate_limit_action_to_string; static const std::map rate_limit_string_to_action; private: const RateLimitRule findLongestMatchingRule(const std::string &nginx_uri) const; static bool is_active; RateLimitAction mode; std::vector rate_limit_rules; }; #endif // __RATE_LIMIT_CONFIG_H__