Scripting Chaos¶
Scripting Chaos progressively increases the complexity of the HTTP tokens required on the checkout journey, to train students in the scripting skills of load testing tools (JMeter, k6, Locust, Gatling): token correlation, double correlation, rotating CSRF, strict sequencing, HMAC signature, and dynamic key derivation.
The goal is not to block the business journey — an order with the right headers always completes regardless of the active level. The goal is to force the tester to progressively enrich their script to keep up with the growing protocol complexity.
Service and endpoint¶
Class: ChaosScriptingService.java
Controller: ChaosScriptingController.java
Admin endpoint: POST /api/admin/chaos/scripting body {"level": 0-4}
Levels¶
| Level | Label | Tokens to manage |
|---|---|---|
| 0 | Disabled | No token required |
| 1 | Junior | 1 token (X-Session-Token) to correlate from login |
| 2 | Intermediate | 2 tokens (Session + Action) — double correlation |
| 3 | Expert | 5 tokens — rotating CSRF + sequential step + HMAC signature |
| 4 | Maestro | Same as Expert + HMAC key derived from sessionToken |
Level 4 uses Maestro instead of Master — it is the only chaos family that deviates from the standard nomenclature, to emphasize the "expert art" nature of the level.
Golden rule¶
The cart remains fully open. Only the login and the 4 checkout steps are protected. The /api/products and /api/cart/* endpoints are never validated by ChaosScriptingService regardless of the active level.
Protected journey¶
sequenceDiagram
participant C as Client (script)
participant L as "POST /api/auth/login"
participant A as "POST /api/checkout/address"
participant S as "POST /api/checkout/shipping"
participant P as "POST /api/checkout/payment"
participant O as "POST /api/orders"
C->>L: step1 — credentials
L-->>C: tokens (Session, Action, CSRF, Step=step2, Sig)
C->>A: step2 — address + tokens
A-->>C: rotated tokens (CSRF, Step=step3, Sig)
C->>S: step3 — shipping + rotated tokens
S-->>C: rotated tokens (CSRF, Step=step4, Sig)
C->>P: step4 — payment + rotated tokens
P-->>C: rotated tokens (CSRF, Step=step5, Sig)
C->>O: step5 — order + rotated tokens
O-->>C: 200 OK
On every Expert/Maestro step, the CSRF, Step, and Signature tokens are regenerated and returned to the client. The tester must capture them in the response and reuse them in the next request — this is the heart of the advanced scripting exercise.
Token bundles¶
ChaosScriptingService stores a TokenBundle per HTTP session in a ConcurrentHashMap<String, TokenBundle> (key = session.getId()). Each bundle holds:
| Field | Mutability | Description |
|---|---|---|
sessionToken |
final | UUID generated at login, never modified |
actionToken |
final | UUID generated at login, never modified |
email |
final | Email of the logged-in account |
csrfToken |
volatile | Rotated at every step (24 bytes base64) |
stepToken |
volatile | step1 → step2 → … → step5 |
signature |
volatile | HMAC recomputed after rotation |
hmacKey |
volatile (Maestro) | Key derived from sessionToken |
Level 1 — Junior¶
Targeted skill: basic correlation of a token from an HTTP response.
| Step | Endpoint | Required headers |
|---|---|---|
| Login | POST /api/auth/login |
(generates tokens in the response) |
| Address | POST /api/checkout/address |
X-Session-Token, X-Request-ID |
| Shipping | POST /api/checkout/shipping |
X-Session-Token, X-Request-ID |
| Payment | POST /api/checkout/payment |
X-Session-Token, X-Request-ID |
| Order | POST /api/orders |
X-Session-Token, X-Request-ID |
The X-Request-ID is generated on the client side (a different UUID per request), the X-Session-Token must be extracted from the /api/auth/login response and reused as-is in all subsequent steps.
Level 2 — Intermediate¶
Targeted skill: double correlation, relogin handling under load.
Login generates three headers instead of two: X-Session-Token, X-Action-Token, X-Request-ID. The first two must be propagated across the 4 checkout steps. The tester must also handle periodic relogin to refresh tokens during long sessions.
Level 3 — Expert¶
Targeted skill: rotating multi-token correlation, strict sequencing, HMAC-SHA256 signature.
At this level, five additional headers appear and three of them rotate at every step:
X-Session-Token— fixed (login)X-Action-Token— fixed (login)X-CSRF-Token— rotated at every checkout step (new 24-byte base64)X-Step-Token— sequential:step2→step3→step4→step5X-Signature— recomputed on every rotation (HMAC-SHA256)
Signature calculation¶
The HMAC signature is computed using the formula:
signature = base64url(HMAC-SHA256(payload, key))
payload = sessionToken + ":" + csrfToken + ":" + stepToken
key = HMAC_SECRET (Expert) | hmacKey (Maestro)
At Expert level, the key is static:
The tester must recompute the signature at every step with the new csrfToken and stepToken values extracted from the previous response.
Level 4 — Maestro¶
Targeted skill: dynamic HMAC key derivation, partial reverse engineering.
Identical to Expert, but the HMAC key is no longer static: it is derived from the sessionToken at login time:
Every session therefore has its own HMAC key, and the tester must recompute this key after every login. To help verify the derivation, login returns an X-Key-Hint header containing the first 8 characters of the derived key — the tester compares their local computation to this hint before signing the first step.
Error codes¶
| HTTP code | Error code | Cause |
|---|---|---|
| 400 | 400 |
Missing mandatory header (Session, Request-ID, Action) |
| 401 | 401 |
X-Session-Token does not match any bundle |
| 401 | E-TKN-99 |
No active bundle — relogin required |
| 401 | E-SIG-07 |
Missing or invalid signature (Expert) |
| 401 | E-HMAC-03 |
Invalid signature (Maestro) |
| 403 | E-CSRF-01 |
Missing or invalid X-CSRF-Token |
| 409 | E-STEP-04 |
Missing or out-of-sequence X-Step-Token |
| 422 | 422 |
X-Action-Token does not match the bundle |
The E-* codes are PerfShop-specific — they let the tester quickly diagnose which element of the protocol failed without ambiguity.
Prometheus metrics¶
| Metric | Type | Description |
|---|---|---|
chaos_scripting_level |
Gauge | Current level (0–4) |
chaos_scripting_bundles_active |
Gauge | Number of active bundles (logged-in sessions) |
The bundles_active counter is useful for observing session memory pressure under load testing — each login creates a bundle that is only cleaned up on HTTP session expiration.
API — admin endpoints¶
# Enable Expert level
curl -X POST https://perfshop-api.perfshop.io/api/admin/chaos/scripting \
-H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
-d '{"level": 3}'
# Current status
curl https://perfshop-api.perfshop.io/api/admin/chaos/scripting/status \
-H "X-Admin-Token: $TOKEN"
# Reset (level 0 + all bundles cleared)
curl -X POST https://perfshop-api.perfshop.io/api/admin/chaos/scripting/reset \
-H "X-Admin-Token: $TOKEN"
API — admin logs¶
# Retrieve the last 100 events (login, OK validations, rejects)
curl https://perfshop-api.perfshop.io/api/admin/chaos/scripting/logs \
-H "X-Admin-Token: $TOKEN"
# Clear the logs
curl -X DELETE https://perfshop-api.perfshop.io/api/admin/chaos/scripting/logs \
-H "X-Admin-Token: $TOKEN"
The activity log keeps the last 100 events, newest first. Each entry contains: ts, type (LOGIN/OK/REJECT/RESET/LEVEL), session (first 8 characters of the session ID), email, token (full token for the admin), detail, ok (boolean).
Public endpoints¶
curl https://perfshop-api.perfshop.io/api/chaos/public/scripting/status
curl https://perfshop-api.perfshop.io/api/chaos/public/scripting/logs
These endpoints are delegated to ChaosScriptingPublicController and expose the state + logs without authentication, to feed real-time monitoring.
Student activation¶
POST /api/chaos/student/scripting body {"level": N} — requires student mode. The level is capped at 1 without a license (freemium), at 4 with a valid license.
Pedagogical relevance¶
| Level | JMeter / k6 skill demonstrated |
|---|---|
| Junior | Regular Expression Extractor on the login response |
| Intermediate | Double extractor, periodic relogin handling |
| Expert | Multi-token extractor, HMAC computation through JSR-223 / crypto.hmac |
| Maestro | Key derivation in a pre-processor, X-Key-Hint verification |