Reports, evidence and audit
Gardience keeps a tamper-evident audit log and can package fleet status, baseline results and the audit log into one evidence pack for auditors.
To open reports: choose Security > Reports and evidence. The page shows:
- Engineer time and cost saved by automation this month.
- The audit chain status: "Intact" or "BROKEN", with the number of entries and when it was last checked.
- The number of nodes in scope.
The Audit log page
Security > Audit log lists every entry, newest first: changes, approvals and other decisions first, reads and routine checks folded away below them, a page at a time. Search by person, machine, action (for example workflow.approved), run or job id, or date; a search looks through the newest 5,000 entries, and Export CSV has every entry. Verify the chain checks that no entry was changed or removed.
What the audit log records
The audit log records:
- Every Salt job started on the Salt master, with the user, function, target and arguments.
- Actions on the Salt master itself: runner and wheel calls that can change something (for example accepting or deleting an agent key, or running an orchestration), with the user and arguments, and every key accepted, deleted or rejected, including with
salt-keyon the server. Read-only master calls (job lookups, cached node details, key listings) are not logged one by one. - Sign-ins and failed sign-ins.
- Changes made in Gardience, such as fixes, runbook saves and API run requests, approvals, locks, change windows, held work, secrets (never their values), event rules, settings and evidence exports.
- The per-node outcome of every change (
job.results): every node that succeeded and every node that failed, with the reason, filed under the run and the person who asked for it. Large changes are split into entries of at most 2,000 nodes, each carrying the job's totals. If the service restarts while a change is running (for example during a long patch wave), the job is remembered from the moment it was sent, and when the service is back its per-node outcomes are collected from Salt's job cache and recorded, marked "collected from Salt's job cache after a service restart interrupted the run". - Events from Gardience itself, such as drift detected by event rules, a gap in the Salt event stream (
audit.gap), and a restore from a backup (system.restored).
For routine read-only jobs on more than 50 nodes, such as scans, an entry lists the first 5 nodes, the node count and a SHA-256 hash of the full node list, to keep the log small. Jobs that change machines always list every node.
The dashboard's Audit log card shows only the latest changes made by people. The CSV export and the evidence pack contain every entry.
Signed evidence packs
Every evidence pack is signed by the install's own Ed25519 evidence key (made on first use, kept on the data volume). The pack carries manifest.json (a SHA-256 for every file), manifest.sig and the public key. The Reports page shows the key's fingerprint: give it to your auditor once, separately from any pack. They then check a pack, with nothing but Python 3 or OpenSSL 3:
python3 tools/verify-evidence.py gardience-evidence.zip --fingerprint FINGERPRINTIt passes only when the signing key matches the fingerprint, the signature is valid, and every file matches the signed manifest, with nothing added. It then checks the contents:
- The audit log is one unbroken chain: every entry names the entry before it, so a removed, added or reordered entry fails the check.
- Per-node results are complete, both ways: every change in
change-results.csvhas its per-node results entry in the audit log, every per-node results entry in the audit log appears inchange-results.csv, and every machine a change was sent to has a result (ok, or failed with the reason).
It prints the totals (changes, node outcomes, ok and failed) and exits non-zero on any failure. tools/verify-evidence.py ships in the release bundle.
How the log is protected
Each entry is chained to the one before it. Its hash is an HMAC-SHA256 of the previous entry's hash plus the entry itself, made with a key kept outside the data volume (in the configuration directory). Changing, inserting or removing an entry breaks the chain from that point on.
After entries are written, Gardience also saves a signed checkpoint with the number of entries and the newest hash. If the log is later cut short, or entries are replaced, the checkpoint no longer matches, even though the remaining entries still chain correctly.
If Gardience cannot write to the audit log (for example, because the disk is full), it refuses changes until it can, and shows the problem on the console.
To keep a copy off the server, set Audit forwarding (syslog / SIEM) in Administration > Settings to a target such as tls://siem.example.com:6514 or udp://192.0.2.5:514. Gardience sends every entry, with its chain hash, as it is written. If the SIEM is down, forwarding resumes from the last entry the SIEM accepted.
Verify the audit log
To verify now: on Overview > Dashboard, choose Verify chain on the Audit log card. Gardience recomputes every hash in every log file and shows "Audit chain intact: N entries verified" or "AUDIT CHAIN BROKEN".
Gardience also verifies the whole chain every 15 minutes in the background. If the chain does not verify, a warning appears on the console.
Verification fails when:
- An entry's hash or its link to the previous entry does not match.
- A line in the log cannot be read.
- The log holds fewer entries than the signed checkpoint recorded, or the entry at the checkpoint is a different one.
- The checkpoint's signature does not verify.
To verify from a script, call GET /gardience/api/v1/audit/verify with a read-only API key.
Clear an audit log alarm
When Gardience finds at start-up that entries were removed or replaced, it raises a lasting alarm. The alarm stays, and verification keeps failing, until people review it. The finding and the review both stay in the log.
- Investigate what happened.
- An admin opens Security > Reports and evidence, describes what the investigation found under Audit log problem (at least a sentence), and chooses Acknowledge.
- A second admin does the same. The alarm clears only after this second person confirms.
On an install with only one admin and no approvers, the first admin's review clears the alarm, and the log notes that no second person was available.
Export the audit log
To download every entry as a CSV file: on Overview > Dashboard, choose Export CSV on the Audit log card. The file has these columns: ts, user, fun, tgt, jid, hash, prev.
The evidence pack's copy of the audit log also includes each entry's arguments.
Only one export or evidence pack is built at a time. If another is in progress, try again in a minute.
To search recent entries from a script, call GET /gardience/api/v1/audit with a read-only API key. It takes limit (up to 500) and q (text to search for).
Download the evidence pack
On Security > Reports and evidence, choose Download evidence pack (.zip). The zip contains these files:
| File | Contents |
|---|---|
summary.html | A printable summary: fleet totals, each node's status, the audit chain result and every baseline control with its observed value. |
compliance.csv | One row per node: OS, Salt agent version, pending updates, baseline score, compliant, whether the baseline was scored, and the pending updates. |
baseline-controls.csv | One row per node and control: control ID, title, reference, result and observed value. |
audit-log.csv | Every audit entry: time, user, action, target, arguments, job ID, previous hash and hash. |
audit-verification.txt | A full chain verification made when the pack was built: time, entry count, result, head hash and the method used. |
change-results.csv | The per-node outcome of every change in the audit chain: time, job ID, who asked, the change, its label and run, node, ok or failed, the reason, and the source when it was collected after a restart. |
drift-history.csv | Recent drift corrections: time, node, who corrected it, the setting and its diff. |
automation-runs.csv | Recent runbook and workflow runs: start and finish times, kind, name, who launched it, status and who approved it. |
cmmc-summary.txt | Present once a CMMC Level 2 assessment has started: the SPRS score, the eligibility status and the counts of met, not met, partly met, not applicable and not assessed requirements. |
cmmc-assessment.csv | One row per NIST SP 800-171 requirement: its value, status, Gardience's evidence, the implementation statement, who is responsible and who assessed it when. |
cmmc-poam.csv | Every open requirement with its value, whether it may be on a POA&M, the planned remediation, milestone and responsible person. |
cmmc-settings.csv | Each machine's CMMC settings checks: the check, the requirement, the result, the observed value and when it was checked. |
manifest.json | When and by whom the pack was made, and a SHA-256 checksum of every other file. |
manifest.sig, evidence-public-key.pem | The install's Ed25519 signature of the manifest, and its public key (see Signed evidence packs). |
Each evidence pack runs a fresh, full verification of the audit chain. Downloading a pack is recorded in the audit log as evidence.exported.
To check that a file has not been changed since the pack was made, compare its SHA-256 checksum with the one in manifest.json:
sha256sum compliance.csvPrintable report
To print or save the summary as a PDF, choose Open printable report (save as PDF) and use your browser's print command. The printable report uses the latest background chain check, which can be up to 15 minutes old. The evidence pack always runs a new one.