ZTP-prem — operator guide¶
Other languages: English · Português · Español
Audience: bench operator + customer security auditor running TLSStress.Art in a Fortune-500 DC under the Zero-Trust-on-Premises 12-camadas posture. This is the day-2 practical guide — for the architectural decision record see SECURITY_ZTP_PREM.md and the ZTP-prem ADR family.
What ZTP-prem is, in one paragraph¶
The threat model is not the external attacker — it is the insider operator with full root shell access to the bench (a DC sysadmin, an auditor's escort, an internal contractor). Twelve camadas (layers) defend against that adversary; each is named, audited individually, and shipped behind a verifiable Tier A (open, customer-auditable) or Tier B (moat-closed, garble- obfuscated) classification. See ADR 0026 for the umbrella.
The 12 camadas at a glance¶
| # | Camada | What it does | Customer touchpoint |
|---|---|---|---|
| 1 | Cloud HSM key custody | Bench never holds raw signing keys | Verify in ADR 0027 |
| 2 | Confidential Computing detect | Surface CC readiness per node | Dashboard /admin/ztp-prem |
| 3 | TPM 2.0 measured-boot probe | Detect TPM surface per node | Dashboard /admin/ztp-prem |
| 4 | Tier A/B code partition | Customer-auditable A; moat-closed B | platform/ztp-prem/tier-policy.yaml |
| 5 | K8s admission webhook | Classify + audit every Pod | Dashboard "Admission audit" |
| 6 | Sealed audit hash-chain | Tamper-evident WORM history | Dashboard "Sealed audit" |
| 7 | Cross-correlation bridge | Admission ↔ sealed audit alignment | Dashboard "Correlation alerts" |
| 8 | UTXO token vault | Note-not-balance licence model | Dashboard "Licence vault" |
| 9 | MÓDULO LICENSE.Art envelope | Signed licence envelope, offline-verifiable | Dashboard "Licence card" |
| 10 | Sealed-key release scaffold | (v6.0+) TPM PCR-anchored key unseal | Planned |
| 11 | DLP egress monitor | Tracked-fetch wrapper, 5 baseline rules | Dashboard "DLP card" |
| 12 | Behavioural anomaly detector | 4 rule-based detectors | Dashboard "Anomaly card" |
Day-2 operational checklist (weekly)¶
# 1. Verify sealed audit chain integrity
kubectl exec -n web-agents deploy/dashboard -- \
node /app/scripts/verify-sealed-audit.mjs --since=7d
# 2. Review admission audit denials + break-glass invocations
kubectl exec -n web-agents deploy/dashboard -- \
node /app/scripts/admission-audit-summary.mjs --since=7d
# 3. Confirm cross-correlation has no drift > 30s
kubectl exec -n web-agents deploy/dashboard -- \
node /app/scripts/correlation-drift.mjs --since=7d
# 4. Inspect DLP egress events
kubectl exec -n web-agents deploy/dashboard -- \
node /app/scripts/dlp-events.mjs --since=7d --rule=any
# 5. Read the behavioural-anomaly detector report
kubectl exec -n web-agents deploy/dashboard -- \
node /app/scripts/anomaly-report.mjs --since=7d
Each script returns a structured JSON document the bench archives
into the sealed audit log under the ops-checklist event class.
Camada 1 + 9 — licence envelope rotation¶
# Cloud-side (HSM operator)
./pkg/ztp-prem-signctl/cmd/ztp-signctl/ztp-signctl sign \
--key=keys/isk.pem \
--in=envelope-2026-Q3.json \
--out=envelope-2026-Q3.signed.json
# Hand-carry the signed envelope to the bench operator (out-of-band
# channel, e.g. encrypted USB). Bench-side, drop into:
# dashboard volume:/data/license/incoming/
# Dashboard auto-ingests on the next vault sync.
The cross-language signing contract (ADR 0027) is byte-stable — if the bench's verifier rejects the envelope, the most common cause is JSON edit in transit. Re-generate from the source, do not edit by hand.
Camada 4 — Tier A/B partition audit¶
# Customer auditor reproduces the partition locally:
cat platform/ztp-prem/tier-policy.yaml
# Verify CI received the same policy for the v3.7.0 release:
gh release view v3.7.0 --json assets -q '.assets[] | select(.name=="tier-policy.yaml.sha256")'
# Hash-match: SHA-256 of the local tier-policy.yaml must match the
# release asset.
Tier B binaries are garble-obfuscated in CI, not via
post-build wrapper. The release SBOM lists garble as part of the
toolchain string — auditor can confirm in
platform/ztp-prem/TIER-B-OBFUSCATION.md.
Camada 5 — K8s admission webhook modes¶
| Mode | When to use | Effect |
|---|---|---|
audit (default) |
Day-one + during baseline collection | Every admission classified + recorded; always Allow |
enforce |
Steady-state production | Missing/invalid tier → Deny |
break-glass (per-pod label) |
Incident response or auditor inspection | Allow under enforce; ticket ID recorded in audit |
Flip from audit to enforce:
kubectl set env -n web-agents deploy/ztp-prem-admission \
ZTP_PREM_ADMISSION_MODE=enforce
# Watch the audit ring buffer for new denials:
curl -sH "Authorization: Bearer $AUDIT_TOKEN" \
https://admission.tlsstress.art/audit | jq '.[-20:]'
The K8s manifest at k8s/ztp-prem/admission-webhook.yaml
embeds a 4-step canary rollout guide (single-replica audit →
multi-replica audit → single-replica enforce → full enforce). Use
it on first production rollout.
Camada 6 + 7 — verifying tamper-evidence¶
# Sealed audit log: hash-chain verification
node /app/scripts/verify-sealed-audit.mjs --full
# Cross-correlation: admission decisions ↔ sealed audit
node /app/scripts/correlation-drift.mjs --full
A chain break is never auto-fixed. The verifier returns:
- Sequence number where the chain broke
- Hash that didn't match the next entry's
prev_hash - Timestamp of the broken entry
Treat as an incident — possible insider tampering or storage corruption. Capture the bench state + escalate per the customer's incident-response playbook.
Camada 11 — DLP rule baseline¶
The DLP wrapper ships 5 baseline rules that catch the project's own sensitive material:
- PEM-format certificate / key material
- K8s ServiceAccount tokens
- Persona webserver TLS material
- Sealed audit hash-chain fragments
- Cloud HSM ISK fingerprints
To add a customer-specific rule (e.g. "block exfil of any URL
matching *.customer-internal.com"):
# dashboard config:/data/dlp/customer-rules.yaml
- name: customer-internal-domain
pattern: '\.customer-internal\.com'
action: record-and-alert # do NOT add 'block' yet — observe-only in v3.7.0
DLP runs in observe-only mode in v3.7.0 (records + alerts, does not block). Block-mode is planned for v6.0+ once false- positive baselines stabilise.
Camada 12 — anomaly detector tuning¶
The 4 detectors ship with defaults appropriate for a Fortune-500 weekday workload:
| Detector | Default threshold | Where to tune |
|---|---|---|
| Denial-flood | >50 denials/min sustained 5min | dashboard:/data/anomaly/denial-flood.yaml |
| Break-glass-burst | >3 uses/hour | dashboard:/data/anomaly/break-glass.yaml |
| Tier-B-ratio-spike | >2σ above 14-day baseline | auto-tuned (read-only) |
| Off-hours-activity | outside 08:00-19:00 customer-TZ | dashboard:/data/anomaly/business-hours.yaml |
Each detector emits a named event into the sealed audit log on fire, so the detection itself is auditable.
Camada 2 + 3 — CC and TPM readiness¶
kubectl get configmap -n web-agents -l ztp-prem.tlsstress.art/probe=detect
kubectl get configmap -n web-agents -l ztp-prem.tlsstress.art/probe=tpm
Each per-node ConfigMap carries the most recent JSON status doc
from the respective probe. Dashboard
/admin/ztp-prem renders fleet-wide coverage.
v3.7.0 posture: probes are advisory — workloads schedule regardless of CC / TPM presence. v6.0+ flips both to mandatory: Tier B Pods will refuse to schedule on non-CC nodes, and the sealed audit log gains a measured-boot PCR anchor.
Compliance audit — what to hand the auditor¶
platform/ztp-prem/tier-policy.yaml— partition source of truthplatform/ztp-prem/TIER-B-OBFUSCATION.md— garble policy- ADR 0026..0033 — design decisions
- Output of the 5 weekly-checklist scripts (last 90 days)
- The release-feed manifest for the running version
- The SBOM + Cosign signature for every running container
For SOC 2 / ISO 27001 / LGPD / GDPR / NIST 800-53 mapping, see
docs/COMPLIANCE_FRAMEWORK_MAPPINGS.md.
Common questions¶
"Can I disable ZTP-prem to simplify a demo?"
You can put the admission webhook in audit mode (default) — that
classifies + records but never blocks. You cannot disable the
sealed audit chain or the Tier A/B partition — those are
build-time properties, not runtime toggles.
"What if the Cloud HSM is unavailable when I need to mint a licence?" The bench runs offline indefinitely on already-minted notes (UTXO model, ADR 0033). New licence material requires a Cloud HSM signing event. For air-gap deploys we recommend pre-minting a batch of notes covering the next 12 months.
"Why is the moat in Tier B if the customer can kubectl exec
into the container?"
kubectl exec reveals the binary, not the source. The garble pass
in CI obfuscates the binary — function names, control flow, and
constants are mangled. The customer can run + audit the binary;
they cannot easily recompile a modified version.
Related¶
- SECURITY_ZTP_PREM.md — architectural posture
- ADR 0026 — umbrella decision
platform/ztp-prem/— tier policy + custody docspkg/ztp-prem-*/— shipping module READMEs
Last verified against shipping code: v3.7.0 (2026-05-12).