Terma BastionPOC

All tests

Test matrix

70 tests, generated from docs/TESTS-AND-DEMOS.md and the timestamped runs in lab/results/. The status comes from the newest run that includes the test; tests never run show the test list's status.

TestScenarioProvesStatus
T1
demo
A clean device on an access port: EAP-TLS with TPM cert → hostapd → controller moves the port from quarantine to its VLAN
Evidence from the latest run

T1 · passed · run 14 Oct 2026, 17:34 CEST

EAP SUCCESS, port Vlan70, gateway reach, audit: {"seq":3,"ts":"2026-10-14T15:34:14.378283053Z","site":"edge-a","src":"gatectl","event":"ADMIT","port":"Ethernet8","mac": (software device key; TPM-backed key in phase 3)
Zero-trust port admission Passed
T2 A device with no TPM cert, or a revoked one, stays in quarantine
Evidence from the latest run

T2 · passed · run 14 Oct 2026, 17:34 CEST

no-cert device: port Vlan20, gateway blocked (revoked-cert case not yet tested)
Default deny at L2 Passed
T3 A device whose FDO voucher is missing or wrong is rejected

No lab run recorded yet. Status from the test list: planned

Supply-chain integrity Planned
T4
demo
A device registered to customer A, plugged into Edge B, stays in quarantine
Evidence from the latest run

T4 · passed · run 14 Oct 2026, 17:34 CEST

customer-B cert: EAP FAILURE, port Vlan20, gateway blocked
Per-customer trust domains Passed
T5 A Talos node boots with Trusted Boot, then the KMS releases its disk key and the node joins
Evidence from the latest run

T5 · passed · run 14 Oct 2026, 18:48 CEST

core(secureBoot=true, UKI=true, EPHEMERAL=luks2) edge-a(secureBoot=true, UKI=true, EPHEMERAL=luks2); Core disk TPM-sealed; Edge A EPHEMERAL key slot = Sidero Labs KMS server on the switch host (https://10.5.20.1:4443), 3 RELEASE entries for node 51bd551e-87d7-4fe0-8d0a-86240ecb2c6d in the append-only log, node joined
Boot gate Passed
T6
demo
A Talos node with a modified boot image (UKI) can't unlock its disk and never joins

No lab run recorded yet. Status from the test list: blocked 2026-10-14: needs our own Secure Boot keys (ADR-028) to boot a modified UKI against; planned phase 3

Boot tamper detection Blocked
T7 The KMS key for a node is revoked, and the node is excluded after reboot
Evidence from the latest run

T7 · passed · run 14 Oct 2026, 18:48 CEST

revoked node 51bd551e-87d7-4fe0-8d0a-86240ecb2c6d rebooted: 5 KMS DENY('node revoked'), EPHEMERAL phase=failed, k8s node NotReady; after restore Talos' own KMS retry unlocked it without another reboot -> Ready
Revocation Passed
T8 A switch host fails a Keylime check, so its SPIRE agent is evicted

No lab run recorded yet. Status from the test list: blocked: no TPM or Keylime on SONiC-VS (ADR-054)

Runtime attestation on switch hosts Blocked
T9 Short SVID lifetimes: a node with its SPIRE entry removed loses its identity within its TTL

No lab run recorded yet. Status from the test list: not run (ADR-054)

Short-lived identity Not run
T10
demo
A workload in Edge A calls Core and succeeds; a call from A to B is rejected
Evidence from the latest run

T10 · passed (identity layer) · run 14 Oct 2026, 17:34 CEST

Edge A SVID (URI:spiffe://edge-customer-a.bastion/workload/sensor, ttl 599s) verifies at Core with the federated edge-customer-a bundle; Core holds no edge-customer-b bundle ('Error: rpc error: code = NotFound desc = bundle not found') so B identities are rejected; workload mTLS call follows with Argo CD-deployed apps (phase 3)
Cross-domain authorization Partial
T11
demo
Only NATS (7222) and the Argo CD path leave an edge; any other outbound attempt is blocked and logged
Evidence from the latest run

T11 · passed (lab border) · run 14 Oct 2026, 17:34 CEST

Edge A pod -> Core: 443 open, 7222 open, 6443 blocked, 4222 blocked, 50000 blocked; switch -> Core 4222 blocked; Core -> Edge 6443 blocked; 23 packets dropped+logged. Enforced by the lab-VM border chain standing in for the SONiC border ACL (ADR-047)
Two-egress rule Partial
T12
demo
The WAN is cut: the edge keeps running, NATS buffers, then the edge reconciles when the link returns
Evidence from the latest runs

T12 · passed · run 14 Oct 2026, 17:34 CEST

WAN cut: Edge A node Ready, 5 readings buffered locally (edge stream=5), Core count 0 during cut; after reconnect Core=5 (replayed). Argo CD resync part follows in phase 3

T12b · passed · run 14 Oct 2026, 18:48 CEST

Argo CD at Edge A: during WAN cut app kept running (ready=1, sync=Synced, Git change not reachable); after reconnect it reconciled to Git rev 6239b93d (ready=2) by pull only
Disconnected operation Passed
T13 Customer B revokes federation: Core loses access to B, and B keeps running

No lab run recorded yet. Status from the test list: planned

Customer sovereignty Planned
T14
demo
Air-gapped update: a signed and encrypted volume on the update port goes through the quarantine VM, signature check, TPM decrypt, local registry and Argo CD

No lab run recorded yet. Status from the test list: blocked 2026-10-14: air-gap path is phase 4

Secure offline updates Blocked
T15
demo
A tampered or unsigned update volume is rejected in quarantine

No lab run recorded yet. Status from the test list: blocked 2026-10-14: air-gap path is phase 4

Update integrity Blocked
T16 Air-gapped data export: JetStream writes to a volume encrypted to Core's key, and Core imports it

No lab run recorded yet. Status from the test list: planned

Secure offline data transfer Planned
T17 The chassis tamper switch fires and keys are wiped

No lab run recorded yet. Status from the test list: planned

Physical tamper response Planned
T18 Tetragon detects an unexpected process or file write in a container

No lab run recorded yet. Status from the test list: planned

Runtime monitoring Planned
T19 A one-command rebuild from Git recreates the lab

No lab run recorded yet. Status from the test list: passed 2026-10-14, partial (lab/up.sh rebuilt the phase-1 lab from scratch in 395 s after down.sh; later phases not yet included)

Reproducibility Partial
T20 Compliance evidence: controls mapped to NIS2 and IEC 62443, with logs from T1–T18

No lab run recorded yet. Status from the test list: planned

Audit readiness Planned
T21
demo
Cold-start bootstrap: power on an empty Edge; it comes up in ADR-016 order with no Core connection
Evidence from the latest run

T21 · passed (partial) · run 14 Oct 2026, 18:48 CEST

WAN cut, KMS restarted, Edge Talos rebooted: 1 local KMS release(s), node Ready, demo app ready=2 from local Argo CD/K8s state with Core unreachable. Switch host was not power-cycled (gate state would need re-provisioning, T62) and FDO/Keylime steps are not built
No chicken-and-egg deadlock Partial
T22 The switch host fails Keylime after boot: SVID denied, KMS stops releasing keys
Evidence from the latest run

T22 · passed (partial) · run 14 Oct 2026, 18:48 CEST

switch host config tampered: 4 KMS DENY('switch measurement mismatch'), Edge A EPHEMERAL phase=failed; reverted -> Ready. Self-check is a hash measurement standing in for Keylime/TPM quote (no TPM in SONiC-VS, ADR-051); SVID denial part needs Keylime
Switch attestation enforcement Partial
T23 A device on the infrastructure port with the wrong TPM fingerprint can't reach the KMS
Evidence from the latest run

T23 · passed (partial) · run 14 Oct 2026, 18:48 CEST

foreign host 10.5.20.77 on the Edge A infrastructure segment (link up) -> KMS 4443 blocked; KMS also rejects any enrolled UUID from a non-pinned source. Binding to the node TPM EK is not possible with the Talos KMS API (UUID only, ADR-051)
Bootstrap port pinning Partial
T24 Rotate a trust domain's intermediate CA from the offline root; SVIDs keep working, and the old intermediate is rejected afterwards
Evidence from the latest run

T24 · passed (partial) · run 14 Oct 2026, 17:34 CEST

core intermediate rotated D889653897F7DE77 -> B6F52517744DB5CC (root key in SoftHSM); spire core: activated X.509 authority 68cbdc7e2ddf38b3b66f477d0bbdaaceed0cf85b (signed by serial=B6F52517744DB5CC); new SVID chains to the new intermediate and verifies to the offline root. Old-intermediate rejection after expiry not exercised
Key management (ADR-018) Partial
T25 An older but validly signed update volume is rejected (rollback), and so is one whose TUF metadata has expired (freeze)

No lab run recorded yet. Status from the test list: planned

Update freshness (ADR-019) Planned
T26 A deliberately compromised switch host unlocks Talos but still gets no workload secrets: no SVID, so SPIRE gates them

No lab run recorded yet. Status from the test list: blocked: needs Keylime (ADR-054)

Limits of circular trust (ADR-021) Blocked
T27 Every Sidero Labs KMS server key release shows up in the append-only log, and a refused release is logged with its reason
Evidence from the latest run

T27 · passed · run 14 Oct 2026, 18:48 CEST

release log: 20 RELEASE, 26 DENY (last reason 'switch measurement mismatch'), 52 entries, 0 chain breaks, file attr +a (a): truncation -> 'Operation not permitted'
Key release audit (ADR-021) Passed
T28 Set the Edge clock backwards, or let it drift: the time floor holds, an alarm is raised, and expired certificates stay rejected

No lab run recorded yet. Status from the test list: planned

Trusted time (ADR-022) Planned
T29 Keep an Edge disconnected for longer than the SVID lifetime (and, sped up, longer than the intermediate CA lifetime): it keeps running locally, then renews via the update volume

No lab run recorded yet. Status from the test list: planned

Long air gap (ADR-023) Planned
T30 Customer A credentials try to publish or subscribe to customer B subjects, and NATS denies them
Evidence from the latest run

T30 · passed · run 14 Oct 2026, 17:34 CEST

cust-a user pub/sub on cust-b.* -> 'Permissions Violation for Publish to '; leaf publish to cust-b.t30 reached customer B: 0 msgs; leaf publish to cust-a.t30 reached Core cust-a: 1
Customer isolation in NATS (ADR-024) Passed
T31 Alter or delete one audit event; the hash-chain check detects it
Evidence from the latest run

T31 · passed · run 14 Oct 2026, 17:34 CEST

Core copy of Edge A gate audit (6 events via leaf->JetStream): 'checked 6 events, 0 bad, 0 restarts, 0 duplicates'; after editing event 2: 'TAMPER at seq 2'
Audit integrity (ADR-025) Passed
T32 Restore etcd and Longhorn from backup, and rebuild an Edge from bare metal using backups and the update volume

No lab run recorded yet. Status from the test list: planned

Recovery (ADR-026) Planned
T33 An update volume containing an image with a known-exploited (CISA KEV) vulnerability is blocked in the quarantine VM

No lab run recorded yet. Status from the test list: planned

Scan policy (ADR-027) Planned
T34 (Production) Export through a hardware data diode: data reaches Core, and nothing can flow back to the Edge

No lab run recorded yet. Status from the test list: planned (prod)

One-way export (ADR-027) Planned
T35 (Paper exercise) Kill-switch walkthrough: revoke federation, disable the NATS account, stop key releases, and confirm the expected effects

No lab run recorded yet. Status from the test list: planned (paper)

Kill switch end state (ADR-027) Planned
T36 A Talos image not signed with our own Secure Boot keys, or with an extra system extension, refuses to boot

No lab run recorded yet. Status from the test list: planned

Own signed image (ADR-028) Planned
T37 Try to boot from USB or the network, or change a firmware setting: blocked, or the Sidero Labs KMS server refuses the disk key

No lab run recorded yet. Status from the test list: planned

Firmware hardening (ADR-029) Planned
T38 A device on an OT or customer VLAN can't reach Argo CD, the Sidero Labs KMS server, SPIRE or the NATS system account

No lab run recorded yet. Status from the test list: planned

Management VLAN separation (ADR-030) Planned
T39 A new pod with no policy can't talk to anything; a pod with the wrong SPIFFE identity is refused
Evidence from the latest run

T39 · passed (partial) · run 14 Oct 2026, 17:34 CEST

namespace default-deny: labelled sensor -> api 'ok', unlabelled intruder -> api 'blocked'. SPIFFE-identity (Cilium mutual auth with SPIRE) not yet enabled
Cilium default deny (ADR-031) Partial
T40
demo
Run the revocation runbook for an Edge: federation, NATS and key release are all cut in one action, and it appears in the audit log
Evidence from the latest run

T40 · passed · run 14 Oct 2026, 17:34 CEST

after one revoke action: Core edge-a bundle certs=0, leaf messages reaching Core=0 (leaf log auth errors: 14), KMS key release stopped for node 135eb9a2-825e-4f3c-beca-d66921734a87 (revoked list entry=1; denial-on-reboot proven in T7), audit entries total=3; restore brought traffic back (1) and re-enabled release
Edge revocation (ADR-032) Passed
T41 An app gets its secret from SOPS at the Edge; the Git repo holds only ciphertext; another node can't decrypt it

No lab run recorded yet. Status from the test list: planned

Application secrets (ADR-033) Planned
T42 Cut power in the middle of an update: the Edge comes back on the last good version

No lab run recorded yet. Status from the test list: planned

Fail safe (ADR-034) Planned
T43 Fill the disk, and insert a corrupt or truncated update volume: the Edge stays up, rejects the bad input and raises an alarm

No lab run recorded yet. Status from the test list: planned

Fail safe (ADR-034) Planned
T44 Threat model review: every STRIDE threat has a mitigating ADR and a test, or is marked as an accepted risk

No lab run recorded yet. Status from the test list: planned

Threat coverage (ADR-035) Planned
T45 The crypto inventory lists every key and algorithm in use, with a post-quantum plan for long-lived data and the root CA

No lab run recorded yet. Status from the test list: planned

Post-quantum readiness (ADR-036) Planned
T46 One person alone can't sign an update, issue a CA or revoke an Edge; a Git change without a second reviewer can't be merged

No lab run recorded yet. Status from the test list: planned

Separation of duties (ADR-037) Planned
T47 Trigger a gate denial, an attestation failure and a revocation: each appears on the dashboard and raises an alert; the "days to air-gap limit" counter is shown per Edge

No lab run recorded yet. Status from the test list: planned

Control observability (ADR-038) Planned
T48 Roll out a deliberately broken version to a canary Edge: health checks fail, it rolls back automatically, and other Edges aren't touched

No lab run recorded yet. Status from the test list: planned

Upgrade policy (ADR-039) Planned
T49 Data on a "restricted" subject is refused by the export job (or only allowed through the diode); "internal" data is exported encrypted

No lab run recorded yet. Status from the test list: planned

Data classification (ADR-040) Planned
T50 Decommission a node: its disk can't be read, its TPM is cleared, and re-plugging it leaves it in quarantine

No lab run recorded yet. Status from the test list: planned

Decommissioning (ADR-041) Planned
T51 Regression: swtpm starts for every lab Talos node. Ubuntu's AppArmor profile blocked swtpm writing to /var/lib/talos-lab; the local override must be named usr.bin.swtpm
Evidence from the latest run

T51 · passed · run 14 Oct 2026, 18:48 CEST

override present, 6 swtpm processes
Lab reproducibility (ADR-044) Passed
T52 Regression: SONiC-VS access ports come up. They are admin-down by default, and config interface startup fails inside the container, so admin_status is set in CONFIG_DB
Evidence from the latest run

T52 · passed · run 14 Oct 2026, 18:48 CEST

Ethernet8 admin=up oper=up
Lab reproducibility (ADR-043) Passed
T53 An authenticated device logs off (EAPOL-Logoff): the port goes back to quarantine VLAN 20 and the gateway is unreachable
Evidence from the latest run

T53 · passed · run 14 Oct 2026, 17:34 CEST

after EAPOL-Logoff: port Vlan20, gateway blocked
Gate closes again (ADR-043) Passed
T54 Regression: an intermediate can only issue IDs in its own trust domain; a customer-B intermediate forging an Edge A SPIFFE ID fails permitted subtree violation
Evidence from the latest run

T54 · passed · run 14 Oct 2026, 17:34 CEST

customer-B intermediate: own-TD cert OK; forging spiffe://edge-customer-a.bastion -> 'permitted subtree violation'
Name constraints (ADR-045) Passed
T55 Regression: Cilium is installed through the Talos 1.14 multi-document patch, with no kube-proxy
Evidence from the latest run

T55 · passed · run 14 Oct 2026, 17:34 CEST

Cilium ready=1, kube-proxy daemonsets=0 (Talos 1.14 multi-doc patch)
Lab reproducibility (ADR-050) Passed
T56 Regression: single-node sites schedule workloads (allowSchedulingOnControlPlanes); a kubectl taint removal is reverted by Talos
Evidence from the latest run

T56 · passed · run 14 Oct 2026, 17:34 CEST

no control-plane taint on core/edge-a (cluster.allowSchedulingOnControlPlanes=true, talos/sched-patch.yaml)
Lab reproducibility (ADR-050) Passed
T57 Known issue: the SPIRE datastore is emptyDir until Longhorn, so a server restart loses federated bundles (fed-sync re-runs)
Evidence from the latest run

T57 · passed (fixed) · run 14 Oct 2026, 17:34 CEST

SPIRE datastore on PVC (local-path/Bound, ADR-052): edge-customer-a federated bundle certs before restart=1, after spire-server restart=1 without fed-sync
Persistence (ADR-050) Passed
T58 Regression: Core streams sourced from the Edge leaf are active and survive hub restarts (hostPath JetStream, leaf JS-API permissions, self-heal)
Evidence from the latest run

T58 · passed · run 14 Oct 2026, 17:34 CEST

TELEM_A_CORE/AUDIT_A_CORE (last-active ns, msgs) = 45960172 5 950696293 7 after hub restart
NATS buffering (ADR-050) Passed
T59 Regression: Core Git answers on 443 (non-root Gitea plus forwarding sidecar)
Evidence from the latest run

T59 · passed · run 14 Oct 2026, 17:34 CEST

Core Git on 443 serves repo bastion/edge-a-config
Two-egress path (ADR-050) Passed
T60 Regression: restarting the audit shipper does not duplicate events at Core (Nats-Msg-Id = event hash)
Evidence from the latest run

T60 · passed · run 14 Oct 2026, 17:34 CEST

audit shipper restart re-sent the log; Core AUDIT_A_CORE stayed at 6 messages (deduplicated)
Audit integrity (ADR-048) Passed
T61 Regression: after a VM stop and start, stale Talos state with no running VM is detected and the site is recreated

No lab run recorded yet. Status from the test list: fixed 2026-10-14 (talos-sites.sh stale())

Lab rebuild (ADR-051) Fixed, not re-run
T62 Regression: local-path storage works on Talos 1.14 multi-document configs (directory UserVolumeConfig, no kubelet extraMounts)

No lab run recorded yet. Status from the test list: fixed 2026-10-14

Storage (ADR-052) Fixed, not re-run
T63 Regression: the control-plane taint in KubeNodeConfig comes back after config changes; untaint.sh removes it from the document

No lab run recorded yet. Status from the test list: fixed 2026-10-14 (T56 passed)

Scheduling (ADR-050) Fixed, not re-run
T64 Regression: the T5 check reads the KMS key slot from VolumeStatus

No lab run recorded yet. Status from the test list: fixed in run-tests.sh, not re-run

Test correctness Fixed, not re-run
T65 Regression: recovery after a KMS deny (T7, T21, T22) can take more than 5 minutes, so the wait is now 10 minutes

No lab run recorded yet. Status from the test list: fixed in run-tests.sh, not re-run

Test correctness (ADR-051) Fixed, not re-run
T66 Known issue: T24 rotation with a persistent SPIRE datastore; SPIRE keeps its old CA until it rotates, so a new SVID does not chain to the new intermediate right away

No lab run recorded yet. Status from the test list: fixed 2026-10-14 (ADR-056, spire-rotate-ca.sh) (evidence)

CA rotation (ADR-018, ADR-052) Fixed, not re-run
T67 Regression: after an intermediate rotation with a persistent SPIRE datastore, a forced local-authority rotation (prepare, then activate) makes new SVIDs chain to the new intermediate

No lab run recorded yet. Status from the test list: passed 2026-10-14, via T24 (evidence)

CA rotation (ADR-018, ADR-052) Passed
T68 The Talos node's infrastructure port is admitted only with 802.1X EAP-TLS using a TPM-backed certificate; a spoofed MAC or IP with a valid node UUID can't reach the KMS (extends T23)

No lab run recorded yet. Status from the test list: blocked 2026-10-14: Talos has no native wired supplicant, needs a system extension in our own image (ADR-028, not started)

ADR-051 compensating control 1 Blocked
T69 Regression: the NATS leaf user may publish $JSC.R.> (replies to the cross-domain source consumer-create), so the Core sourced streams are active right after setup
Evidence from the latest run

T69 · passed · run 14 Oct 2026, 17:34 CEST

leaf user allows pub $JSC.R.>; TELEM_A_CORE/AUDIT_A_CORE source last-active ns = 735434239 728823112 (not -1)
Disconnected operation (ADR-056) Passed
T70 Open: the recovery and readiness check (eready/ephase in run-tests.sh) after a KMS deny or a cold start never reports Ready, although the app answers and the node is Ready later. Debug the helper in the next VM session

No lab run recorded yet. Status from the test list: fixed 2026-10-14: the helper read metadata.phase (always "running") instead of spec.phase (evidence)

Test correctness Fixed, not re-run