The `sleep 4` / `sleep 3` after a decision change were magic numbers tied to
updateIntervalSeconds / defaultDecisionSeconds. Replace them with waits on the
actual condition:
- After a ban/unban, poll with wait_for_status until the expected code shows up
(stream propagation / live-mode cache TTL).
- Captcha keeps status 200 before and after, so gate on the body marker via a
new wait_for_body_contains helper.
- Control assertions that must NOT change stay immediate (assert_status).
Self-documenting, faster on the happy path (returns on the first poll that
sees the change), and more robust under slow CI. No fixed sleeps remain.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per review, trim the mock to the minimum the plugin actually exercises:
- Drop the stream delta bookkeeping (startup flag + "already streamed" set).
The plugin re-Sets/Deletes its cache on every poll, so reporting the whole
active set as "new" and removed ones as "deleted" is enough.
- Shrink the Decision struct to the three fields the plugin reads
(value/type/duration); drop id/origin/scope/scenario and the id counter.
- Drop API-key auth and the /admin/reset endpoint — no scenario exercises
either. Also drop the now-unused lapi_reset helper.
- Replace the store struct + methods with two package-level maps + a mutex.
mocklapi/main.go: 234 -> 118 lines. All six scenarios still pass.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Per review, split the e2e work so each PR is focused. CI runs the binary +
mock-LAPI suite (this PR); the heavier, local-only Docker suite (real Traefik
+ Crowdsec, incl. appsec) now lives in #333.
Removes tests/e2e/scenarios, tests/e2e/lib and the Docker-suite README, and
drops the `e2e` Make target here (kept in #333). The binary/mock suite and its
`e2e_mock` target are unchanged.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Document the --backend-addr flag: it is the stub upstream service Traefik
proxies allowed requests to (the traefik/whoami equivalent), not AppSec.
- Move the .cache/ ignore rule from the per-suite .gitignore to the repo root
.gitignore, and make the wording accurate: the cache persists across local
runs but is recreated on every (fresh-runner) CI run.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add a second e2e suite that runs Traefik as a downloaded binary with the
plugin loaded from source, and replaces Crowdsec with a small stdlib-only Go
LAPI mock driven via /admin endpoints. No Docker, no real Crowdsec.
The mock lives in its own nested Go module (tests/e2e/mock/mocklapi) so it
stays out of the plugin module's build, lint, test and vendor.
This suite validates the plugin's own behaviour (live/none/stream modes,
caching, trusted-IP bypass, ban/captcha rendering). Crowdsec and AppSec
correctness are out of scope on purpose — they are validated upstream by the
maintainer — so the AppSec scenario is intentionally absent and the README
says so to avoid misfiled issues.
CI now runs this suite only (`make e2e_mock`), since it needs neither Docker
nor a real Crowdsec. The Docker suite (tests/e2e/scenarios) is kept for local
debugging (`make e2e`).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The matrix spawned one runner per scenario, so the Traefik, Crowdsec and
whoami images were pulled — and Crowdsec booted — once per scenario. Run
the whole suite in a single job with `make -k e2e` instead: Docker caches
the images locally so they are pulled only once, and `-k` keeps the
remaining scenarios running after a failure (make still exits non-zero).
Scenarios already share the canonical `crowdsec` container name and the
8000 port, so they were meant to run sequentially anyway.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
appsec-virtual-patching only ships CVE-specific rules, not generic
SQLi. Switch to crowdsecurity/appsec-crs-inband (the blocking OWASP
Core Rule Set) and use a SQLi probe that CRS paranoia level 1
matches (rule 942100/942130).
Crowdsec v1.7 refuses to start without an explicit volume mount on
/var/lib/crowdsec/data (or the bypass env var). For E2E we don't need
db persistence — set the bypass everywhere so the stack boots.
Reverts the stream-mode scenario to the Traefik docker provider (the
file provider was a workaround for a local docker daemon API version
mismatch, irrelevant in CI). Bumps Traefik to v3.7.1 and Crowdsec to
v1.7.8 across all scenarios.
Adds six new E2E scenarios:
- live-mode: short defaultDecisionSeconds, verifies cache-then-recheck
- none-mode: verifies LAPI is queried per request, no caching
- trusted-ips: clientTrustedIPs bypass even when the trusted IP is banned
- custom-ban-page: BanHTMLFilePath body + Content-Type validation
- captcha: captcha decision serves the captcha page (HTTP 200)
- appsec: SQLi probe blocked by appsec-virtual-patching
Each scenario uses an isolated compose project, mounts the repo as a
local plugin, and asserts behavior via curl. Workflow matrix and
Makefile E2E_SCENARIOS updated accordingly.
Refs #328
Add tests/e2e/ structure with shared bash helpers and the first
scenario (stream-mode): spin up real Traefik + Crowdsec via docker
compose, mount the repo as a local plugin, add a ban via cscli, verify
the bouncer blocks the matching X-Forwarded-For, then delete the
decision and verify pass-through.
Adds .github/workflows/e2e.yml with one matrix job per scenario
(stream-mode for now), and Makefile targets `e2e` and `e2e_<scenario>`
for local runs.
Refs #328
* 🐛 fix(user-agent) add version in ua to reduce warning logs from crowdsec LAPI
* 🐛 fix(user-agent) add version in ua to reduce warning logs from crowdsec LAPI
* 🐛 fix(user-agent) remove whitespaces
* 🐛 fix(user-agent) Add Cap for Bouncer
---------
Co-authored-by: maxlerebourg <maxlerebourg@gmail.com>
* ✨ Add ban html template
* 📝 Add doc for custom ban page
* ⚰️ Remove old code due to merge
* ✏️ Fix merge remaining in html
* ✨ render banTemplate from html/template to string
* 🚨 : fix lint
---------
Co-authored-by: max.lerebourg <max.lerebourg@monisnap.com>
* 📝 Clean documentation in Readme
* 📝 Update readme
* 📝 Place exemples in seperated README
* ⬆️ Update traefik to 2.9.6 and crowdsec to 1.4.3 in exemples
* 📝 Add exemple at the right place
* 📝 Add documentation exemple 4 for vm binary usage
* :hammer:Update binary version
* 🔨 update
* 🔨 update
* 🚧 Working Crowdsec with tls auth
* 🐛 Add changes to download the plugin from the service
* 🔧 Add config middle for https
* 🔧 Update config for the exemple
* 🔧 Add conf for certs, working example
* 📝 Add doc for binary vm Readme
* 📝 update documentation for exemple and make
* 🚨 Fix lint
* 🚨 Fix Lint End of File
* ✨ Add support for insecure tls connections to LAPI
* 📝 Add documentation for the TLS insecure parameter
* 🚧 Add tls authority certificate and checks for params
* 📝 Add example for tls communication in readme and folder
* 📝 Update documentation and example for tls
* 🚨 Fix easy lint errors
* 🦺 logic to fetch certificates
* 🚨 Fix lint on readme
* ♻️ Refactor validate to fix lint and clean
* 🚧 Add doc, cert gen for crowdsec example
* 🚧 Progress on setting up Crowdsec with tls
* 🚧 Update certs validation for example
* ♻️ Add load variable from file or value and get client cert
* ♻️ Refactor getting variables
* 🚨 Fix lint, no new line on new files
* 🐛 Fix bug on condition check lapi key cert
* ♻️ Update after review
* ♻️ Update after review
* 🍱 fix mathieu code
* ♻️ Refactor logic of loading tls certificates
* 🍱 clean code
* 🍱 last fix
* 🍱 fix lint
* ♻️ Add documentation in readme, fix lint, remove unfinished tests
* 🐛 Fix conditions logics
* 🚨 Fix Lint
* ♻️ simplify code on getVariable
Co-authored-by: Max Lerebourg <maxlerebourg@gmail.com>