mirror of
https://github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin.git
synced 2026-07-21 19:48:59 +02:00
✅ e2e mock: add AppSec scenario + custom remediation header assertion
Address review feedback on the binary e2e suite: - mocklapi: add an AppSec WAF stand-in (--appsec-addr) that blocks any URI containing "rpc2" — the exact probe from examples/appsec-enabled — and allows the rest. Lets the suite exercise the plugin's AppSec wiring (header forwarding + allow/block enforcement) without the real CRS engine. - new scenarios/appsec: benign request passes, /foo/rpc2 is 403. - custom-ban-page: assert the banned response carries the custom remediation header (remediationHeadersCustomName), per review. - README: drop the "don't open issues / AppSec intentionally absent" framing; describe what the suite actually covers, including AppSec wiring. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -4,9 +4,10 @@
|
||||
// test drive decisions through /admin instead of `cscli`. It also serves the
|
||||
// stub upstream that Traefik proxies allowed requests to.
|
||||
//
|
||||
// It is deliberately NOT a Crowdsec/AppSec conformance harness: Crowdsec's own
|
||||
// correctness is the upstream maintainer's responsibility, not this plugin's.
|
||||
// See the suite README.
|
||||
// It is NOT a Crowdsec/AppSec conformance harness — the real WAF engine (OWASP
|
||||
// CRS, virtual patching) is out of scope. The AppSec endpoint here emulates a
|
||||
// single deterministic rule so the suite can exercise the plugin's AppSec
|
||||
// wiring (header forwarding, allow/block handling) end to end. See the README.
|
||||
package main
|
||||
|
||||
import (
|
||||
@@ -14,6 +15,7 @@ import (
|
||||
"flag"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
@@ -48,6 +50,8 @@ func main() {
|
||||
// The stub upstream Traefik proxies allowed requests to — the binary-suite
|
||||
// equivalent of the traefik/whoami container. Not AppSec.
|
||||
backendAddr := flag.String("backend-addr", "127.0.0.1:8091", "address for the stub upstream service")
|
||||
// AppSec WAF stand-in (the real engine listens on :7422). Not a CRS engine.
|
||||
appsecAddr := flag.String("appsec-addr", "127.0.0.1:8092", "address for the AppSec mock")
|
||||
flag.Parse()
|
||||
|
||||
go func() {
|
||||
@@ -56,6 +60,19 @@ func main() {
|
||||
})))
|
||||
}()
|
||||
|
||||
// AppSec mock: the plugin forwards the request metadata in X-Crowdsec-Appsec-*
|
||||
// headers and reads our status — 200 allows, 403 blocks. We emulate one
|
||||
// deterministic virtual-patching rule (block any URI containing "rpc2", the
|
||||
// exact probe from examples/appsec-enabled) so the plugin's AppSec path is
|
||||
// exercised without standing up the real WAF.
|
||||
go func() {
|
||||
log.Fatal(http.ListenAndServe(*appsecAddr, http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if strings.Contains(r.Header.Get("X-Crowdsec-Appsec-Uri"), "rpc2") {
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
}
|
||||
})))
|
||||
}()
|
||||
|
||||
mux := http.NewServeMux()
|
||||
|
||||
// Readiness probe for the test harness (empty body, 200).
|
||||
@@ -113,6 +130,6 @@ func main() {
|
||||
}
|
||||
})
|
||||
|
||||
log.Printf("mocklapi: LAPI on %s, backend on %s", *lapiAddr, *backendAddr)
|
||||
log.Printf("mocklapi: LAPI on %s, backend on %s, appsec on %s", *lapiAddr, *backendAddr, *appsecAddr)
|
||||
log.Fatal(http.ListenAndServe(*lapiAddr, mux))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user