Checkpoint Lab — Security, Data Protection, Authorization, and Safe Load-Test Boundaries
The checkpoint asks for two proofs: first, a non-allow-listed target must fail safely before networking or JMeter starts; second, the authorized local run must stay inside the 30-sample boundary while its fake credential and request-body values remain absent from retained artifacts.
Learning objectives
- Complete the chapter checkpoint for Security, Data Protection, Authorization, and Safe Load-Test Boundaries as one reviewable, bounded experiment.
- State the workload, predictions, acceptance criteria, authorization boundary, and abort conditions before execution.
- Reconcile configured versus achieved work with JTL, jmeter.log, target evidence, and generator validity before making a conclusion.
- Produce an evidence packet that records the exact inputs, results, diagnosis or gate outcome, and any material limitations.
- Perform cleanup or rollback and explain how the checkpoint evidence hands off to the next chapter or operating practice.
1. Exact assumptions and ceilings
| Item | Checkpoint baseline |
|---|---|
| JMeter/Java | Apache JMeter5.6.3 / Java17 / no third-party plugins. |
| Tooling | Python3 standard library only. |
| Authorized target | http://127.0.0.1:8031 and POST /work only. |
| Identity/data | Fake token + synthetic user/request IDs only. |
| JMeter load | 3 threads ×10 loops =30 configured samples; pacing200ms (must remain ≥150ms). |
| Duration | Launcher hard timeout15s. |
| Target kill boundaries | max30 work attempts; max25 requests/s. |
| Results | Lean CSV JTL + matching jmeter.log + dashboard; no bodies/headers/URL. |
| Retention | Illustrative local7-day evidence policy; cleanup after review. |
| Denied-target requirement | SCOPE_DENIED=30; network_attempted=false; jmeter_invoked=false. |
2. Freeze the evidence/protocol before traffic
- Review
scope/authorization.json. - Hash scope, JMX and safe.properties.
- Verify target fixture command binds only to127.0.0.1 and ceilings30/25.
- Verify JMX uses properties for token/target and exact3×10 workload.
- Verify result-save policy disables bodies/headers/URL.
- Set only the documented fake token.
3. Predictions before execution
P1 — denied target: passing
https://example.com as input will return exit30 before
DNS/network/JMeter; guard evidence will show both booleans false and
local target work_attempts remains0.
P2 — allowed run: exact loopback target produces30 successful JTL samples and30 target successes with no auth/scope/rate rejection.
P3 — secret boundary: the fake token never appears in JMX, CLI arguments, JTL, jmeter.log, dashboard or target events; only a SHA-256 fingerprint/redacted bearer marker can be retained.
P4 — cleanup: temporary secret properties are gone when launcher exits and target port8031 is closed after fixture shutdown.
4. Start authorized target/preflight
$env:P31_FAKE_TOKEN = "p31-fake-token-4e65d5cf"
python .\fixtures\safe_target.py `
--host 127.0.0.1 --port 8031 `
--max-requests 30 --max-rps 25 `
--log .\results\target-events.jsonl
Keep this fixture shell open. In a second shell inspect
/health; do not send /work manually.
5. Demonstrate non-allow-listed target fails before traffic
python .\tools\safe_launcher.py `
--scope .\scope\authorization.json `
--target-url https://example.com `
--jmx .\plans\safe-load.jmx `
--properties .\config\safe.properties `
--threads 3 --loops 10 --pacing-ms 200 `
--out .\results\rejected-target
$DeniedExit = $LASTEXITCODE
if ($DeniedExit -ne 30) { throw "Expected exit30" }
Get-Content .\results\rejected-target\guard.json
curl.exe --fail --silent http://127.0.0.1:8031/stats
Require: scope denied; no network/JMeter invocation by the launcher; target work_attempts=0. The public-looking URL string is never contacted.
6. Execute the authorized bounded plan
python .\tools\safe_launcher.py `
--scope .\scope\authorization.json `
--target-url http://127.0.0.1:8031 `
--jmx .\plans\safe-load.jmx `
--properties .\config\safe.properties `
--threads 3 --loops 10 --pacing-ms 200 `
--out .\results\authorized
if ($LASTEXITCODE -ne 0) { throw "Authorized run failed" }
The launcher validates scope/workload first, checks health, creates a short-lived secret properties file, invokes JMeter CLI, removes the token from JMeter's inherited environment, deletes the temporary file and records its status.
7. Independently verify load and guard state
Get-Content .\results\authorized\guard.json
curl.exe --fail --silent http://127.0.0.1:8031/stats
(Get-Content .\results\authorized\results.jtl | Measure-Object -Line).Lines
Get-Item .\results\authorized\jmeter.log,
.\results\authorized\dashboard\index.html
Expect exactly30 data rows plus CSV header, target successes=30, zero auth/scope/rate failures, launcher PASS and temporary-secret deletion true.
8. Prove evidence is redacted
python .\tools\scan_artifacts.py `
--root .\results\authorized `
--secret-env P31_FAKE_TOKEN `
--out .\results\authorized\redaction-scan.json
if ($LASTEXITCODE -ne 0) { throw "Redaction scan failed" }
Also inspect target events: only
Bearer <redacted>, token fingerprint, body
hash/field names/size and timing may appear. No raw request
body/body values are retained.
9. Abort procedure
During a real authorized run, immediately stop/kill the generator when any predeclared abort condition fires; stop remote engines if applicable; target-side guard should reject excess traffic independently. Preserve current JTL/log/target/guard evidence before deleting processes/files. For this local lab, Ctrl+C/Stop-Process is sufficient because no remote engine exists.
10. Cleanup and audit
Stop the fixture, then:
python .\tools\cleanup_audit.py `
--host 127.0.0.1 --port 8031 `
--guard .\results\authorized\guard.json `
--redaction-scan .\results\authorized\redaction-scan.json `
--out .\results\cleanup-audit.json
Remove-Item Env:P31_FAKE_TOKEN
Get-Content .\results\cleanup-audit.json
Require cleanup PASS: port closed, temp secret file deleted, redaction PASS and allowed run PASS.
11. Required evidence packet
| Artifact | Required |
|---|---|
| Authorization/scope | authorization.json + SHA; exact target/path/method/purpose/window. |
| Guard | rejected-target guard.json proving zero network/JMeter; authorized guard.json. |
| Workload | 3×10=30, pacing200, timeout15s, target30/25 ceilings. |
| Secret source | Fake env var reference only; no raw value in retained evidence. |
| Result evidence | JTL + matching jmeter.log + dashboard + target stats/events. |
| Redaction | redaction-scan PASS + lean JTL field policy. |
| Abort plan | Explicit 401/403/429/5xx/count/resource/redaction conditions and operator action. |
| Cleanup | cleanup-audit PASS + environment variable removed. |
| Validity | Configured/achieved30 and no guard-trigger distortion before performance interpretation. |
12. Example checkpoint conclusion
13. Production operating-model addition and Chapter32 bridge
Chapter31 adds a safe-load-test governance contract: explicit authorization, exact target allow-list, trusted JMX/code review, synthetic/masked-data decision, secret-injection boundary, TLS/RMI identity verification, independent workload/time/rate aborts, configured-versus-achieved reporting, lean/redacted artifacts, restricted retention/access and cleanup/audit are required before a performance test is operationally acceptable.
Chapter32 moves to Plugins, Custom Components, JMeter APIs, and Extension Strategy. That chapter expands JMeter's executable surface, so the trust lessons here become supply-chain and extension-design requirements: every plugin/JAR/custom sampler is code with version, provenance, privilege and data-access implications.
Knowledge check
What independently proves the denied URL generated no traffic?
guard.json has network_attempted=false/jmeter_invoked=false and target stats remain zero.
Why doesn't a fake-token leak have the same incident impact as a real secret?
The token is deliberately non-production/disposable, but the scan still validates the retention mechanism before it is used with real systems.
If the target returns429 at sample20, can you call the planned30-sample performance result valid?
No. The safety boundary worked, but achieved workload differs; preserve evidence and diagnose before any capacity/regression claim.
What should happen before adding a staging hostname to the allow-list?
Obtain explicit owner authorization and define target/path/dependencies/data/TLS/workload/abort/retention boundaries.
What security concern carries directly into Chapter32?
Plugins/custom components are executable code and may read secrets/data/network/files, so provenance/review/version/least-privilege boundaries matter.
Official references and version notes
- Apache JMeter downloads — current stable JMeter 5.6.3 and Java 8+ requirement.
- JMeter current changes — Java 17+ recommendation for the 5.6.x line.
- Apache JMeter Security Model — JMX is trusted input and may execute arbitrary code; isolate untrusted plans.
- JMeter Component Reference — Authorization Manager passwords are stored unencrypted in the test plan; recorder certificate behavior and SSL components.
- JMeter Properties Reference — result-save fields and RMI SSL settings.
- JMeter Remote Testing — RMI SSL defaults and keystore setup.
- HTTP(S) Test Script Recorder — recording workflow and temporary CA trust requirements.
Version-sensitive statements were rechecked against current
primary documentation on 2026-09-05. The mandatory runtime is
Apache JMeter 5.6.3 with Java 17 and no
third-party plugin. JMeter 5.6.3 requires Java 8+; Java 17+ is
recommended for 5.6.x. Apache's security model explicitly treats
JMX as trusted input because plans may execute arbitrary code;
never run an untrusted JMX without isolation/review. Authorization
Manager credentials are saved unencrypted in JMX, so the lab does
not put a credential there. CSV result policy explicitly keeps
response data, request/response headers, sampler data and URL off;
current defaults for those sensitive fields are already false, but
the lab pins them explicitly. Since JMeter 4.0, RMI transport uses
SSL by default; server.rmi.ssl.disable defaults
false. The supplied RMI keystore helper creates a seven-day
keypair by default; remote mode remains optional and is not used
in the lab. The HTTP(S) recorder's generated certificates use
proxy.cert.validity, default seven days; its
generated CA should be trusted only in a disposable recorder
browser profile and removed afterwards.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.