Sign in Get API keys
User guide

Device posture policies

Posture policies enforce device-health requirements before a machine can access tagged resources. Out-of-compliance devices are auto-quarantined. This guide covers what signals are collected, how to write a policy, and how the remediation flow works.

Signals collected

The ztna agent reports these on every heartbeat (every 60 seconds):

os_versionstring

E.g. Ubuntu 24.04.1 LTS, macOS 14.4.1, Windows 11 23H2.

disk_encryptionbool

LUKS2 (Linux), FileVault (macOS), BitLocker (Windows). Active state.

firewallbool / string

ufw, iptables, pf, Windows Firewall — any active host firewall.

antivirusbool / string

clamav, XProtect, Defender, third-party AV. Active service required.

screen_lockbool + interval

Auto-lock enabled + maximum idle minutes.

auto_updatebool

OS auto-update enabled.

agent_versionsemver

Version of the ztna binary running.

custom_attributesmap

Custom signals from external-posture integrations (Crowdstrike, SentinelOne).

Writing a posture policy

A policy is a named set of required signal values. Machines matching the policy's scope (by tag or group) must pass every requirement to be marked compliant.

{
  "name": "strict-prod",
  "scope": {
    "tags": ["tag:prod", "tag:engineer"]
  },
  "requirements": {
    "os_version_min": {
      "linux":   "22.04",
      "darwin":  "13.0",
      "windows": "10.0.19041"
    },
    "disk_encryption": true,
    "firewall": true,
    "screen_lock": { "enabled": true, "max_idle_min": 10 },
    "agent_version_min": "3.2.0"
  },
  "on_fail": "quarantine",
  "grace_period_min": 30
}

Enforcement

After every heartbeat, the backend evaluates the device against any matching policies.

  • Compliant — all requirements pass. Machine is online, normal ACL eval applies.
  • Non-compliant + grace period active — user is warned via dashboard + agent notification, but still connected.
  • Non-compliant + grace expiredon_fail action applies.

on_fail options:

warn

Notify admin + user. No enforcement change.

restrict

Deny connections to tagged resources; allow tailnet connectivity.

quarantine

Full isolation. No connections in or out. Can be lifted by admin or remediation.

Applying a policy

$ curl https://login.quickztna.com/api/db/posture_policies \
    -H "Authorization: Bearer $QZ_API_KEY" \
    -d '{
      "rows": [{ /* policy JSON */ }],
      "org_id": "org_9fX2kR"
    }'

Or in the dashboard: Device Security → Posture Policies → New.

Checking a device

$ ztna posture status
Device Posture · laptop-alex
─────────────────────────────
OS Version:           Ubuntu 24.04.1 LTS     ✓ (required: 22.04+)
Disk Encryption:      LUKS2 (active)         ✓
Firewall:             ufw (enabled)          ✓
Antivirus:            clamav (active)        ✓
Screen Lock:          enabled (5min)         ✓
Auto-Update:          enabled                ✓
Agent version:        3.2.0                  ✓ (required: 3.2.0+)

Server verdict: COMPLIANT — all checks pass
Matched policy: strict-prod
$ ztna machines list --filter posture=non_compliant
NAME              IP             VIOLATIONS                                 GRACE
legacy-vm         100.64.1.55    os_version (20.04 < 22.04), agent (3.0.1)  expired
prototype-01      100.64.1.88    disk_encryption, screen_lock                 28 min left

Remediation flow

When a policy fires:

  1. User sees in-dashboard notification + email with exact violations
  2. Dashboard shows "Remediation steps" — sudo ufw enable, "enable FileVault in Settings", etc.
  3. After remediation, user runs ztna posture status to self-verify
  4. Next heartbeat (within 60s) reports fixed state — backend auto-unquarantines
# User sees dashboard: "Your device is quarantined because disk encryption is disabled."

$ sudo fdesetup enable     # macOS — enable FileVault
# (reboot, enter password)

$ ztna posture status
Disk Encryption:  FileVault (active)  ✓
Server verdict: COMPLIANT

# User is automatically unquarantined at next heartbeat

External posture sources

Pull signals from your existing EDR (Crowdstrike Falcon, SentinelOne) via /api/external-posture. The agent combines internal signals with external ones before the server evaluates.

$ curl https://login.quickztna.com/api/external-posture \
    -H "Authorization: Bearer $QZ_API_KEY" \
    -d '{
      "action": "configure_source",
      "org_id": "org_9fX2kR",
      "provider": "crowdstrike",
      "api_client_id": "...",
      "api_secret": "...",
      "sync_interval_min": 15
    }'

Using posture in ACL rules

Combine posture with ACL for a belt-and-braces approach. require_posture: true in a rule means "source must be compliant before this rule matches":

{
  "name": "posture-gated-prod-access",
  "src": "tag:engineer",
  "dst": "tag:prod",
  "proto": "tcp",
  "ports": "22,443",
  "require_posture": true
}

Even if the source machine isn't quarantined, an ACL rule with require_posture denies the connection if posture is failing. Gives layered defence.

See also