fix: neutralize persisted inverted TPP on the coraza edge path (#252 follow-up)#274
Merged
Conversation
Add a quarantined, expected-red e2e case asserting the controller withholds an already-persisted inverted-paranoia TrafficProtectionPolicy from the coraza edge data plane, so benign traffic still serves 200 instead of the CRS 901500 fail-closed 500. The test injects a grandfathered inverted policy by bypassing the #251 CEL admission rule (patch the paranoiaLevels validation off the CRD, create the policy, restore the rule), then asserts a benign GET returns 200. It fails until #252's skip-attachment is enforced on the downstream-gateway path, so it lives under test/e2e-nonblocking and is excluded from the gating test-e2e run via the separate test-e2e-nonblocking target. The controller-side fix that makes this pass is to follow on this branch.
An inverted-paranoia TrafficProtectionPolicy (OWASP CRS detection below blocking) makes CRS rule 901500 fail closed and 500 every request. #252 set Accepted=False/Invalid and skipped attachment on the controller's EnvoyPatchPolicy path, but the live edge enforces coraza through the extension server, which builds per-route directives in a separate path (internal/extensionserver/cache) that #252 never touched. A grandfathered inverted policy therefore still 500'd benign traffic on the downstream gateway. Gate the extension server's directive emission on the same inverted-level check the controller uses, so an inverted policy produces no directives and the mutation layer withholds it from the data plane. A benign request is then unaffected instead of 500'ing. Key changes: - add shared TrafficProtectionPolicySpec.InvertedParanoiaLevels predicate and route both the controller resolve-error guard and the extension server emission through it - return nil directives for an inverted policy in computeCorazaDirectives so ApplyTPPRouteConfig skips the route - add API and emission-layer unit tests: inverted not emitted, valid and equal levels emitted - promote the neutralization e2e into the gating test/e2e suite and drop the now-empty test-e2e-nonblocking target Fixes #273. Refs #252, #242, #268.
ecv
force-pushed
the
fix/273-neutralize-inverted-edge
branch
from
July 13, 2026 23:19
8b2a047 to
d0ca80a
Compare
The benign-GET probe returned HTTP 000 (connection refused), not the neutralized 200, because two harness defects fired before the WAF path was ever exercised: - the probe script had no timeout, so chainsaw's ~5s default killed the 40-attempt retry loop after 2 attempts; - nothing waited for the freshly-created waf-gw to reach Programmed=True, so the probe hit the cold-start window. Add a 180s script timeout and gate the probe on Gateway Programmed=True (3m, matching the enforce test), so the loop retries into the ready window. The controller fix under test is unchanged.
ecv
marked this pull request as ready for review
July 13, 2026 23:41
scotwells
approved these changes
Jul 13, 2026
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.
What
Follow-up to #252. Makes the controller genuinely withhold an already-persisted inverted-paranoia
TrafficProtectionPolicy(blocking > detection) from the coraza edge data plane, so benign traffic serves 200 instead of the CRS 901500 fail-closed 500. Also promotes the neutralization e2e (split out of #272) into the gating suite.Root cause
#252 set
Accepted=False/Invalidand skipped attachment — but only on the controller'sEnvoyPatchPolicypath (internal/controller/trafficprotectionpolicy_controller.go). The livedatum-downstream-gatewayenforces coraza through the extension server, which builds per-route directives in a completely separate path (internal/extensionserver/cache/index.go→computeCorazaDirectives) that #252 never touched. So a grandfathered inverted policy still emitted its corazaSecRulesto the edge and 500'd benign traffic — confirmed in prod (kev-httpbin~53k 500s/24h,pcep-lol-hnqr6o~17k/24h). See #273.Fix
TrafficProtectionPolicySpec.InvertedParanoiaLevels()inapi/v1alpha, and route both the controller resolve-error guard (fix: flag inverted TrafficProtectionPolicy paranoia levels via status condition #252's behavior, unchanged) and the extension-server emission through it — the inverted check is no longer duplicated.computeCorazaDirectivesreturnsnilfor an inverted policy, soApplyTPPRouteConfigskips the route (itslen(governing.Directives) == 0guard) and the golang coraza filter stays disabled for that route. Benign traffic is unaffected.Accepted=False/Invalidstatus behavior is preserved.Tests
api/v1alpha:InvertedParanoiaLevels— inverted reported, equal/higher-detection/no-ruleset not.internal/extensionserver/cache: emission-layer — inverted → no directives (index build +computeCorazaDirectives), valid and equal levels → emitted.go test ./...(non-e2e),go vet,make generate(no diff),make lint(0 issues) all green locally.e2e
Promoted
trafficprotectionpolicy-neutralize-invertedinto the gatingtest/e2e/suite (dropped the now-emptytest-e2e-nonblockingtarget) so this PR's own E2E check validates the fix end-to-end in the downstream-WAF kind env (#268). The benignGET / → 200assertion now describes neutralized behavior rather than an expected-red defect. Kind e2e can only be confirmed by CI — if the E2E check reds, the move is trivially revertible back to quarantine.Notes
Fixes #273. Refs #252, #242, #268, datum-cloud/infra#3408.