Repository navigation
fix(dynamic-rules): apply rules over the base config and wire the agent, the interval and the response modifier - #84
Merged
Conversation
…nt, the interval and the response modifier (#83) Dynamic rules now apply exactly as the Python reference does: ip_blacklist bans for ip_ban_duration and ip_whitelist unbans, the country, cloud provider, user agent and endpoint rate limit values replace the base values, emergency mode always halves the auto-ban threshold, each new version is applied over the base config (guard-core #169), and the events carry the reference envelopes. SecurityConfig::with() keeps the agent and dynamic rule fields, enableAgent is stored and required by enableDynamicRules and enableEnrichment, and dynamicRuleInterval and customResponseModifier are new fields. GuardEngine builds the DynamicRuleManager at initialize(), fetches rules through a per-request interval gate, and applies the response modifier once to every response it returns.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #83
I brought dynamic rules, the agent wiring and the custom response modifier to the Python reference (guard-core master at 859ac345, including guard-core #169). I kept it as one PR and one commit: the wiring and the modifier share
SecurityConfigand the engine with the rule changes, and the singlebin/test_dynamic_rules.phprunner covers both, so a split would leave a red first half.Dynamic rules (
src/Rules):ip_blacklistbans through the engine ban manager forip_ban_durationseconds andip_whitelistunbans, instead of merging into the static lists.blocked_countries,whitelist_countries,block_cloud_providers,blocked_user_agentsandendpoint_rate_limitsreplace the base values (unknown cloud providers dropped, an all-invalid list empties the value),global_rate_windowonly applies with aglobal_rate_limit, country rules without a geo resolver warn and skip, and emergency mode always halves the auto-ban threshold in effect.bin/test_dynamic_rules.phpwith the same scenarios and values.dynamic_rules,previous_version, applied counters, and the missingemergency_mode_activated). The three conformance xfail entries this fixes are removed from the PHP baselines (evt_dynamic_rules_update_apply,evt_emergency_mode_activated,rio_dynamic_rules_snapshot_write).SecurityConfig::with()no longer dropsenableAgent,enableDynamicRules,agentEnableEvents,agentEnableMetricsanddynamicRulesCachePath, an injected geo resolver survives a config without country lists, and every installed candidate carries a fresh revision so the pipeline rebuilds.DynamicRulesobject,auto_ban_thresholdandauto_ban_durationkeep the reference minimum of 1, and the snapshot rendersZtimestamps and an object for an emptyendpoint_rate_limits.Wiring and modifier:
enableAgentis stored.enableDynamicRulesandenableEnrichmentnow require it (the referencevalidate_agent_config), which is a breaking change for configs that set either withoutenableAgent.agent_api_keyis not modelled because the PHP engine never builds the agent, the adapters inject a handler.GuardEngine::initialize()builds theDynamicRuleManagerwhenenableDynamicRulesis on and an agent handler withgetDynamicRules()is attached (warning and static config otherwise, as the reference), and hydrates the last-known rules. The reference runs a background loop; a PHP request has none, soexecute()calls the manager's interval gate: the first request fetches, then one fetch perdynamicRuleIntervalseconds (new config field, default 300, minimum 60, as the reference). guard-agent-php drives its own rules refresh fromtick()for the same reason. Under FPM each worker keeps its own clock and a fresh worker hydrates from the last-known snapshot.customResponseModifieris a new config field, applied once (after the security headers, before the CORS headers) to every response the engine returns, withGuardEngine::applyResponseModifier()for the pass-through responses adapters send. An exception leaves the response unmodified. Adapters need to call that seam to modify their pass-through responses.Docs:
AGENTS.md,docs/usage.md,docs/configuration.md,README.mdand the examples no longer sayenableAgentfails validation or that dynamic rules are unsupported, and the metrics persistence claim now matches the engine, which builds the collector without a Redis handler.Test and gate evidence (host PHP 8.5, a private Redis on port 6391 because
test_ratelimitandtest_geo_rate_limitsrunFLUSHDB):bin/test_dynamic_rules.phpfails on master and passes here, and every runner inci.ymlplus the coverage gate passes. The ecosystem gate runs the four adapter suites against this branch.