Repository navigation
2.0.0 #9
rennf93
announced in
Announcements
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Guard Core v2.0.0 — Release Notes
Why this release
Four operator-facing capabilities ship together because they form a coherent surface for tuning detection in production:
ThreatBanConfigmakes that per-category.RedisCloudIpStoreinstead of every replica fetching independently.Plus a
DetectionResultdataclass replacing the legacy(bool, str)tuple, so threat categories and scores are addressable everywhere they're produced.What's in the box
Area 1 — Detection exclusion knobs
SecurityConfig.excluded_detection_headers / _params / _body_fields(global) and matchingRouteConfigfields withNone= inherit semantics.SecurityConfig.enabled_detection_categories(defaults to all 16) with a validator that rejects unknown labels.@security.detection_exclusion(headers=, params=, body_fields=, categories=)decorator.ALL_DETECTION_CATEGORIESfrozenset andCATEGORY_CONTEXT_MAPconstant for downstream code that wants to enumerate or reason about categories."custom"and run regardless ofenabled_categoriesfiltering.Area 4 — Per-category ban + DetectionResult
DetectionResult(is_threat, trigger_info, threat_categories, threat_scores)dataclass replacestuple[bool, str]everywheredetect_penetration_attemptanddetect_penetration_patternswere used.ThreatBanConfig(threshold, duration)model with category validator.SecurityConfig.threat_ban_config: dict[str, ThreatBanConfig]— first category to cross its own threshold short-circuits the flat fallback."penetration_attempt:<category>"(per-category) or"penetration_attempt"(flat).GuardMiddlewareProtocol.suspicious_request_countsnowdict[str, dict[str, int]](IP → category → count). Total still reachable viasum(values()).BehaviorRule.ban_duration(consumed by_execute_ban_action, defaults to 3600 when unset).Area 2 — Global behavior rules + 404-noise correlation
BehaviorRuleConfigPydantic model:rule_type,threshold,window,pattern,action,ban_duration,correlate_with_detection.SecurityConfig.global_behavior_rules: list[BehaviorRuleConfig]— applies to every route, no decorator needed.BehavioralProcessor.process_global_return_rules()halves the rule's threshold (floor 1) whencorrelate_with_detection=TrueAND the IP has any positive count insuspicious_request_counts.BehavioralContext.middlewarefield; tracker access uses the_behavior_tracker()precedence helper (context first, decorator fallback) so global rules work without a decorator.ErrorResponseFactory.process_response()accepts an optionalprocess_global_behavioral_rulescallback;client_ipis extracted once and shared.Area 3 — IP lifecycle + pluggable cloud-IP store
SecurityConfig.lazy_init: bool = Falsedefers IPInfo MMDB download and cloud-IP fetches to the first request.SecurityConfig.geo_ip_db_max_age: int = 86400(validated 3600 ≤ x ≤ 604800) replaces the hardcoded 86400 inIPInfoManager.SecurityConfig.cloud_ip_store: CloudIpStoreProtocol | None = None— pluggable backend.IPInfoManager.refresh()andGeoIPHandler.refresh()/close()protocol methods.CloudIpStoreProtocolwithInMemoryCloudIpStore(default) andRedisCloudIpStore(auto-upgraded when Redis is wired).CloudManager.set_store(...), store-first reads with API-fetch + write-back fallback. Legacyredis_handler-only path preserved when_store is None.redis_handler: RedisHandlerProtocol | None,agent_handler: AgentHandlerProtocol | Noneinstead ofAny.cloud_ranges(CSV) toguard:cloud_ip(JSON list).Tooling cleanup
schemeProtocol parameter whitelisted; 4unreachable code after raisecases intest_handlers_integration.pyrewritten as class-based context managers (no deadyield).setup_custom_loggingcloses file handlers explicitly — fixes aResourceWarningfor_io.FileIOthat was emitted underpytest -W error::ResourceWarning.unasync.pyrewrite rule for multi-linefrom tests.conftest import (...)and a new substitution rule forcloud_ip_store_protocol(with properSyncCloudIpStoreProtocolrename matching project convention).tests/conftest.pyredis_cleanupfixture now teardowns Redis state afteryieldin addition to before — removes a previously-hidden test-order dependency.Breaking changes — migration recipes
1.
detect_penetration_attempt()returnsDetectionResultSame migration applies to
detect_penetration_patterns().2.
suspicious_request_countsis now nested3. Compiled-pattern tuples are 3-tuples
4. Redis cache namespace
No code change needed. On upgrade, the old
cloud_rangeskeys go stale (TTL expires naturally) and the newguard:cloud_ipnamespace is populated on next refresh. If you have ops dashboards reading the old keys directly, point them atguard:cloud_ip:*instead.Compat notes
lazy_init=Falseis the default — existing eager startup is preserved.enabled_detection_categoriesdefaults to the full set — detection coverage is unchanged unless explicitly narrowed.threat_ban_configdefaults to empty — flat-threshold behaviour preserved unless per-category entries are added.Test posture
make integration-test).What's Changed
Full Changelog: 1.2.1...2.0.0
This discussion was created from the release 2.0.0.
All reactions