Chapter 31Lesson 05~320 minutes

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.

CheckpointFail closed30-sample ceilingSecret redactionCleanup audit

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.
Abort immediately: any non-loopback traffic, 401/403/429/5xx, >30 work attempts, result/target count mismatch, generator saturation, raw token/header/body in retained evidence, temporary secret file not deleted, scope ambiguity, or target owner/fixture control lost.

2. Freeze the evidence/protocol before traffic

  1. Review scope/authorization.json.
  2. Hash scope, JMX and safe.properties.
  3. Verify target fixture command binds only to127.0.0.1 and ceilings30/25.
  4. Verify JMX uses properties for token/target and exact3×10 workload.
  5. Verify result-save policy disables bodies/headers/URL.
  6. 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

Example form: “The approved lab scope allowed only http://127.0.0.1:8031 POST /work with max3 threads,10 loops,30 samples, pacing≥150 ms and15 s duration. A non-allow-listed URL was rejected with exit30 before any network request or JMeter invocation; the local target remained at zero work attempts. The authorized JMeter5.6.3/Java17 run produced30 successful JTL samples and30 target successes with zero auth/scope/rate rejection. The fake token was injected at runtime through a temporary private property file rather than JMX/CLI, removed from the JMeter child environment, and the file was deleted after execution. Lean JTL policy plus artifact scanning found no raw token, Authorization value or request body. Cleanup confirmed the target port closed. These controls demonstrate safe fail-closed behavior for the local fixture; they do not constitute authorization for any staging/production/public system.”

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?

Why doesn't a fake-token leak have the same incident impact as a real secret?

If the target returns429 at sample20, can you call the planned30-sample performance result valid?

What should happen before adding a staging hostname to the allow-list?

What security concern carries directly into Chapter32?

Next chapter

Plugins, Custom Components, JMeter APIs, and Extension Strategy

Chapter32 applies code/provenance/security boundaries to JMeter extensions.

Official references and version notes

Version and compatibility note

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.