defend-audit report is the command that turns the device's continuous audit data into a single, signed, take-it-to-the-auditor evidence ZIP for any past period. It's the headline operator command behind Compliance Reporting — every reference in that page to "one terminal command produces a signed evidence ZIP" is this subcommand.
Renamed in audit-deb 2.0.0. This was previously called
do-audit-report. Thedefend-auditoperator multi-tool now hosts theverify,key-rotate, andreportsubcommands; the old separatedo-audit-*Python scripts were removed. The functionality is unchanged — only the command spelling.
Where to run it: Open the Cockpit admin interface and click Tools → Terminal. Or SSH to the device.
defend-auditis on the$PATHas a regular user — it needssudoto read the audit state under/opt/data/auditor/.
| File | What it is |
|---|---|
events.csv |
Every IDS event in the period |
decisions.csv |
Every CrowdSec decision in the period |
dns_events.csv / file_events.csv / tls_events.csv |
Ransomware indicators (DGA, transferred-file hashes, suspicious TLS) |
config-snapshot.tar.gz |
Suricata, CrowdSec, nftables, ulogd, chrony, and node-exporter configuration at report time |
manifests/MANIFEST-YYYY-MM-DD.json |
The daily Ed25519-signed manifest for every day in the period |
manifests/MANIFEST-YYYY-MM-DD.tsr |
RFC 3161 trusted timestamp for each manifest (audit-deb 2.1.0+); only present if the TSA was reachable when the manifest was signed |
chrony-logs/ |
NTP attestation — proof the device clock was disciplined |
report.pdf (optional) |
Rendered snapshot of the Audit Evidence Grafana dashboard |
manifest.pubring.json |
Device's signing-key ring (for offline verification by the auditor) |
chain-of-custody.json |
Ed25519-signed SHA-256 manifest of every other file in the ZIP |
The ZIP itself is written with mode 0640, root-owned. Safe to copy onto a USB drive, attach to a support ticket, or upload to a compliance portal.
defend-audit report --from YYYY-MM-DD --to YYYY-MM-DD [--out PATH]
[--no-pdf] [--no-config-snapshot]
[--grafana-url URL] [--json]
--from and --to are inclusive UTC dates. If you omit --out, the ZIP is written into the current working directory as defend-o-tron-audit-FROM-to-TO.zip.
| Flag | Required? | Default | Effect |
|---|---|---|---|
--from YYYY-MM-DD |
Yes | — | Inclusive start of the audit period, in UTC. |
--to YYYY-MM-DD |
Yes | — | Inclusive end of the audit period, in UTC. Must be on or after --from. |
--out PATH |
No | ./defend-o-tron-audit-FROM-to-TO.zip |
Output filename. The destination directory must exist; intermediate dirs are not created. |
--no-pdf |
No | off | Skip the Grafana PDF render. Use this if grafana-image-renderer isn't deployed in your fleet. |
--no-config-snapshot |
No | off | Skip the config-snapshot.tar.gz step. Useful if the auditor only wants events, or you're sharing a slimmer bundle. |
--grafana-url URL |
No | from audit.conf [report] grafana_url |
Override Grafana base URL used for the render API. Rarely needed. |
--json |
No | off | Emit a stable JSON envelope on stdout instead of human-readable text, for use by other tooling. |
Generate a Q2-coverage bundle for an auditor:
$ sudo defend-audit report --from 2026-04-01 --to 2026-06-30 \
--out /home/admin/q2-evidence.zip
[defend-audit report] period: 2026-04-01 .. 2026-06-30 (UTC)
[defend-audit report] events: 14,827 rows
[defend-audit report] decisions: 4,113 rows
[defend-audit report] dns_events: 248 rows
[defend-audit report] file_events: 31 rows
[defend-audit report] tls_events: 19 rows
[defend-audit report] config snapshot: /etc/suricata, /etc/crowdsec, /etc/nftables.d,
/etc/nftables.conf, /etc/ulogd.conf,
/etc/chrony/chrony.conf, /etc/chrony/conf.d,
/etc/default/prometheus-node-exporter
[defend-audit report] manifests: 91 days copied (91 with sibling .tsr)
[defend-audit report] chrony logs: /var/log/chrony copied
[defend-audit report] grafana PDF: rendering dashboard 'audit-evidence' … ok
[defend-audit report] pubring: /opt/data/auditor/keys/manifest.pubring.json copied
[defend-audit report] chain-of-custody: signing 11 files (key A4kP7w2…) … ok
[defend-audit report] zipping → /home/admin/q2-evidence.zip
[defend-audit report] mode 0640, owner root:root … ok
OK Success: 1 file written, 138 MB.
The same export, on a fleet without grafana-image-renderer and without the config snapshot:
$ sudo defend-audit report --from 2026-04-01 --to 2026-06-30 \
--no-pdf --no-config-snapshot \
--out /tmp/slim.zip
[defend-audit report] period: 2026-04-01 .. 2026-06-30 (UTC)
[defend-audit report] events: 14,827 rows
[defend-audit report] decisions: 4,113 rows
[defend-audit report] dns_events: 248 rows
[defend-audit report] file_events: 31 rows
[defend-audit report] tls_events: 19 rows
[defend-audit report] config snapshot: skipped (--no-config-snapshot)
[defend-audit report] manifests: 91 days copied (91 with sibling .tsr)
[defend-audit report] chrony logs: /var/log/chrony copied
[defend-audit report] grafana PDF: skipped (--no-pdf)
[defend-audit report] pubring: /opt/data/auditor/keys/manifest.pubring.json copied
[defend-audit report] chain-of-custody: signing 9 files (key A4kP7w2…) … ok
[defend-audit report] zipping → /tmp/slim.zip
OK Success: 1 file written, 12 MB.
Quarterly audit cadence:
# Q1
sudo defend-audit report --from 2026-01-01 --to 2026-03-31 --out ~/q1.zip
# Q2
sudo defend-audit report --from 2026-04-01 --to 2026-06-30 --out ~/q2.zip
Quick one-month bundle for an insurance review:
sudo defend-audit report --from 2026-05-01 --to 2026-05-31 --out ~/insurance-review.zip
A single day, for an incident-response timeline:
sudo defend-audit report --from 2026-05-14 --to 2026-05-14 --out ~/incident-2026-05-14.zip
Machine-readable output (for scripting):
sudo defend-audit report --from 2026-05-01 --to 2026-05-31 --out /tmp/may.zip --json | jq .result
report_meta inside chain-of-custody.json. An auditor verifying the bundle later can use this to match against the corresponding schema.chain-of-custody.json is signed with the device's currently-active key. If the key has rotated since the underlying daily manifests were signed, the per-day manifests still verify against the older key (it stays in the pubring). See defend-audit key-rotate..tsr anchors the signature to the TSA's external clock, which catches device-clock drift independently.defend-audit report always includes whatever .tsr siblings exist alongside the period's manifests. If the TSA was unreachable when a particular day's manifest was signed, that day's .tsr will be missing from the bundle until do-audit-tsr-retry has backfilled it.