Skip to content

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:

  1. PEM-format certificate / key material
  2. K8s ServiceAccount tokens
  3. Persona webserver TLS material
  4. Sealed audit hash-chain fragments
  5. 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

  1. platform/ztp-prem/tier-policy.yaml — partition source of truth
  2. platform/ztp-prem/TIER-B-OBFUSCATION.md — garble policy
  3. ADR 0026..0033 — design decisions
  4. Output of the 5 weekly-checklist scripts (last 90 days)
  5. The release-feed manifest for the running version
  6. 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.


Last verified against shipping code: v3.7.0 (2026-05-12).