What We’re Testing
When a machine sends a posture report and fails one or more policy checks, the server’s behavior depends on the posture_enforcement mode set in org_settings:
“enforce” mode (auto-quarantine):
- If the machine is
onlineand posture evaluation fails, the server setsmachines.status = 'quarantined' - A
machine.auto_quarantineaudit event is logged to Loki - A realtime WebSocket event is broadcast:
{ table: 'machines', type: 'UPDATE', data: { id, status: 'quarantined' } } - The posture-report response returns
quarantined: true - If AI Operator mode is enabled for the org, the server may create
agent_commandsfor auto-remediation (e.g.,enable_firewall,enable_disk_encryption)
“monitor” mode (log only):
- The compliance evaluation runs and violations are recorded in
posture_reports - The response returns
compliant: falseand lists violations - The machine status is NOT changed — it remains
online quarantinedin the response isfalse
“disabled” mode (no evaluation):
- The posture report is stored with
compliant: trueand empty violations - No policy evaluation occurs at all
Quarantine behavior:
- Quarantined machines still send heartbeats, but the heartbeat handler preserves the
quarantinedstatus and only updateslast_seen(line 31 inmachine-heartbeat.ts) - The heartbeat response for a quarantined machine returns
status: 'quarantined',quarantined: true, and an empty peer list - The Go client enters a QUARANTINE state and polls
POST /api/posture-reportevery 60 seconds; if the device becomes compliant, the server sets status back toonlineand the client transitions to COMPLIANT, then reconnects
Auto-unquarantine:
- When a quarantined machine sends a posture report that passes all checks, the server sets
machines.status = 'online'and logs amachine.auto_unquarantineaudit event - This only happens in
enforcemode
Important edge case:
- Machines with status
offlineare NOT quarantined even if non-compliant. The server only quarantines machines whose current status isonline(line 103 inposture-report.ts).
Your Test Setup
| Machine | Role |
|---|---|
| ⊞ Win-A | Browser for dashboard + API verification |
| 🐧 Linux-C | Non-compliant machine (Linux VM without disk encryption, ClamAV, or firewall rules) |
Prerequisites:
- A posture policy exists with
require_disk_encryption = true,require_firewall = true, andrequire_antivirus = true(created in Chapter 51) - Posture enforcement is set to
enforceon the org (Chapter 51, ST3) - 🐧 Linux-C is connected and status is
online
ST1 — Trigger Quarantine via Posture Report
What it verifies: A connected Linux machine without disk encryption, firewall rules, or ClamAV is automatically quarantined when posture enforcement is in enforce mode.
Steps:
- On 🐧 Linux-C , confirm the machine is online:
ztna status
- Force a posture report by running:
ztna posture status
If the machine lacks LUKS encryption, has no iptables rules, and ClamAV is not running, the output should show:
Device Posture Status
-------------------------------------
OS: linux/amd64
Disk Encryption: disabled
Firewall: disabled
Antivirus: disabled
Compliance: NON-COMPLIANT
Violations:
- disk_encryption_required
- firewall_required
- antivirus_required
- On ⊞ Win-A , check the machine status:
$token = "YOUR_JWT_TOKEN"
$machineId = "LINUX_C_MACHINE_ID"
Invoke-RestMethod -Uri "https://login.quickztna.com/api/db/machines?id=eq.$machineId" `
-Method GET `
-Headers @{ Authorization = "Bearer $token" }
Expected behavior:
- The machine
statusis nowquarantined - On the dashboard Machines page, the machine shows a quarantine badge
Pass: Machine status changed from online to quarantined after the non-compliant posture report.
Fail / Common issues:
- Status still
online— check thatposture_enforcementisenforce(notmonitorordisabled). Queryorg_settingsto verify. - Status
offline— the machine went offline before the posture report. Quarantine only applies toonlinemachines.
ST2 — Verify Quarantined Machine Heartbeat Behavior
What it verifies: A quarantined machine continues to heartbeat, but the server does not change its status back to online — it stays quarantined.
Steps:
-
On 🐧 Linux-C , the client should still be running after quarantine. The agent enters the QUARANTINE state and continues polling.
-
On ⊞ Win-A , check the machine’s
last_seentimestamp:
$token = "YOUR_JWT_TOKEN"
$machineId = "LINUX_C_MACHINE_ID"
$result = Invoke-RestMethod -Uri "https://login.quickztna.com/api/db/machines?id=eq.$machineId" `
-Method GET `
-Headers @{ Authorization = "Bearer $token" }
$result.data[0] | Select-Object status, last_seen
- Wait 30 seconds and query again.
Expected behavior:
statusremainsquarantinedlast_seenupdates (the heartbeat handler updateslast_seeneven for quarantined machines)- The heartbeat response to the client includes
quarantined: trueand an empty peer list
Pass: Machine stays quarantined but last_seen advances, confirming heartbeats are still processed.
Fail / Common issues:
- Machine goes
offline— the client may have disconnected. Checkztna statuson Linux-C. - Machine becomes
online— this should NOT happen unless a compliant posture report was sent. Check the posture report in ST3.
ST3 — Check Posture Report Violations in Database
What it verifies: The posture_reports table contains the correct violation codes after a non-compliant evaluation.
Steps:
On ⊞ Win-A , query the posture report:
$token = "YOUR_JWT_TOKEN"
$machineId = "LINUX_C_MACHINE_ID"
Invoke-RestMethod -Uri "https://login.quickztna.com/api/db/posture_reports?machine_id=eq.$machineId" `
-Method GET `
-Headers @{ Authorization = "Bearer $token" }
Expected response:
{
"success": true,
"data": [
{
"id": "<uuid>",
"machine_id": "<machine-id>",
"org_id": "<org-id>",
"os_version": "linux/amd64",
"disk_encrypted": false,
"firewall_enabled": false,
"antivirus_enabled": false,
"compliant": false,
"violations": [
"disk_encryption_required",
"firewall_required",
"antivirus_required"
],
"reported_at": "2026-..."
}
]
}
The violation codes are generated by the posture-report handler:
disk_encryption_required— whenpolicy.require_disk_encryptionis true andbody.disk_encryptedis falsefirewall_required— whenpolicy.require_firewallis true andbody.firewall_enabledis falseantivirus_required— whenpolicy.require_antivirusis true andbody.antivirus_enabledis falsepatch_age_exceeded (N > M days)— whenbody.patch_age_daysexceedspolicy.max_patch_age_days
Pass: Violations array contains the expected codes matching the policy requirements and the machine’s actual posture state.
Fail / Common issues:
violationsis empty — the enabled policy may not have the expected requirements toggled on. Check the policy withGET /api/db/posture_policies.compliantis true — enforcement may bedisabled, which skips evaluation and always storescompliant: true.
ST4 — Verify Monitor Mode Does NOT Quarantine
What it verifies: In monitor mode, non-compliant machines are flagged but NOT quarantined.
Steps:
- On ⊞ Win-A , switch enforcement to
monitor:
$token = "YOUR_JWT_TOKEN"
$orgId = "YOUR_ORG_ID"
$body = @{
action = "update_org_settings"
org_id = $orgId
posture_enforcement = "monitor"
} | ConvertTo-Json
Invoke-RestMethod -Uri "https://login.quickztna.com/api/org-management" `
-Method POST `
-Headers @{ Authorization = "Bearer $token"; "Content-Type" = "application/json" } `
-Body $body
-
If 🐧 Linux-C is currently quarantined, it will not auto-unquarantine in monitor mode (auto-unquarantine only works in
enforcemode). Manually set the machine back toonlinevia the machine admin API or wait for a compliant report in enforce mode first. Alternatively, switch briefly toenforce, fix the posture issue, then switch tomonitor. -
Once the machine is
onlineinmonitormode, trigger a posture report:
ztna posture status
- On ⊞ Win-A , check the machine status:
Invoke-RestMethod -Uri "https://login.quickztna.com/api/db/machines?id=eq.$machineId" `
-Method GET `
-Headers @{ Authorization = "Bearer $token" }
Expected behavior:
statusremainsonline(NOT quarantined)- The posture report shows
compliant: falsewith violations - The
POST /api/posture-reportresponse returnsmode: "monitor"andquarantined: false
Pass: Non-compliant machine stays online in monitor mode. Violations are logged but not enforced.
Fail / Common issues:
- Machine gets quarantined — enforcement may still be
enforce. Verify org_settings. - Cached settings — the heartbeat handler caches
org_settingsfor 3600 seconds. If you just changed the mode, the cache may still have the old value. Wait or restart the API container.
ST5 — Verify Non-Compliant Machine Gets Empty Peer List
What it verifies: When a machine is quarantined, its heartbeat response contains an empty peer list, effectively isolating it from the mesh network.
Steps:
-
Ensure 🐧 Linux-C is in
quarantinedstatus (switch enforcement back toenforceand trigger a non-compliant posture report if needed). -
On 🐧 Linux-C , check peer connectivity:
ztna peers
Expected behavior:
- The peer list is empty or the command indicates the machine is quarantined
- The heartbeat handler (line 32 in
machine-heartbeat.ts) returnspeers: []for quarantined machines - Attempting to
ztna pinganother machine should fail because no peers are available
- Verify via API on ⊞ Win-A by checking the machine detail:
Invoke-RestMethod -Uri "https://login.quickztna.com/api/db/machines?id=eq.$machineId" `
-Method GET `
-Headers @{ Authorization = "Bearer $token" }
The status field should be quarantined.
Pass: Quarantined machine receives no peers in heartbeat response and cannot communicate with other mesh nodes.
Fail / Common issues:
- Machine can still reach peers — there may be a cached peer list from before quarantine. The WireGuard tunnel stays up until the next heartbeat cycle removes the peers.
- Client crashes — older client versions may not handle the quarantine state gracefully. Ensure v3.2.0+.
Summary
| Sub-test | What it proves |
|---|---|
| ST1 | Non-compliant machines are auto-quarantined in enforce mode |
| ST2 | Quarantined machines continue to heartbeat but stay quarantined |
| ST3 | Violation codes are correctly stored in posture_reports.violations |
| ST4 | monitor mode logs violations without quarantining |
| ST5 | Quarantined machines receive empty peer lists (network isolation) |