DEV Community

Cover image for How We Built a Tamper-Evident Audit Log for SOC 2 and ISO 27001 Evidence
gentlyding
gentlyding

Posted on Originally published at logaudit.toolsder.com

How We Built a Tamper-Evident Audit Log for SOC 2 and ISO 27001 Evidence

Most teams treat "audit logging" as an afterthought: pipe everything into a SIEM or a big Elastic cluster, then hope the auditor is satisfied. In practice, that's where the pain starts.

I'm Qin Kang, and I built Log Audit Platform after watching a client burn roughly six engineering-months duct-taping Splunk + spreadsheets together for an ISO 27001 audit. The result was expensive, fragile, and the auditor still asked the one question that sinks most log pipelines:

"How do I know these logs weren't edited after the fact?"

This post walks through how we designed an audit log that an auditor can actually trust — without sending your data to a third party.


1. Why auditors don't trust raw logs

A raw log file is just text. Even if it's shipped to a "secure" bucket, nothing cryptographically ties one line to the next. An attacker (or a well-meaning operator) who gains write access can quietly rewrite history:

  • Change a DELETE into a READ.
  • Backdate an event.
  • Remove the record of a privilege escalation entirely.

When an auditor asks "can you prove this wasn't altered?", a raw log answers with trust me. That's not good enough for SOC 2 (CC7.2 / CC8.1) or ISO 27001 (A.8.15 / A.8.16).

The fix isn't "more storage". It's integrity by construction.


2. What SOC 2 and ISO 27001 actually want from logging

Stripped of jargon, the control families want three things:

  1. Completeness — you captured the events that matter (auth, admin actions, config changes, data access).
  2. Integrity — a record, once written, can't be silently changed.
  3. Availability for review — an auditor (or your own security team) can independently verify both of the above.

Notice the word independently. SOC 2 and ISO 27001 auditors don't just take your word for it; they want evidence they can re-run. That's the design goal we optimized for.


3. Hash-chain design: why a sequential hash works for audit logs

Instead of storing events as isolated rows, every record carries the hash of the previous record's hash chain. Conceptually:

record[0].hash = H(payload[0])
record[n].hash = H(payload[n] || record[n-1].hash)
Enter fullscreen mode Exit fullscreen mode


If an attacker tampers one record, its hash changes and every subsequent link fails verification — the auditor sees exactly where the chain breaks.

Verification walks the chain from the oldest record to the newest. If any payload was altered — even a single character — the recomputed hash at that link no longer matches the stored hash, and every subsequent link breaks too. The verification report marks exactly where the chain was broken.

Why a simple sequential chain rather than a full Merkle tree? For an audit log, records are append-only and verified in order, so a linear chain is simpler to verify, easier to explain to an auditor, and has no reconstruction complexity. (We're looking at optional RFC 3161 timestamp anchoring as a future external-WORM option, but the in-chain integrity is the core.)

The practical takeaway: editing one record is mathematically impossible to hide.


4. GDPR right-to-erasure without breaking the chain

GDPR's right to erasure (Art. 17) collides with an immutable log: you can't just DELETE FROM audit_log a user's rows, because that breaks the chain and the audit trail.

Our approach is cryptographic erasure / anonymization, not physical deletion:

  • Personal data is stored in a separate, keyed store, referenced by token from the audit record.
  • On a valid erasure request, we destroy the key material for that subject. The audit record remains (required for the integrity trail), but the linked identity becomes unrecoverable ciphertext.
  • The hash chain stays intact, because we erase the key, not the log.

This satisfies both sides: the regulator gets erasure; the auditor keeps a verifiable timeline.


5. Evidence pack automation: turning logs into auditor-ready ZIPs

The second thing auditors hate is hunting. They don't want your raw database; they want the control mapped to the evidence.

So we ship evidence packs: pre-built, exportable bundles that map collected events to specific control IDs (e.g. SOC 2 AC-2, ISO 27001 A.8.16). One click produces a ZIP containing:

  • The relevant filtered records.
  • A hash-chain verification report (proving the bundle itself is intact).
  • A control-to-evidence mapping sheet.

The auditor runs the verification themselves. No spreadsheet gymnastics, no "trust me".


6. Self-hosted deployment: one JAR

Compliance data shouldn't leave your perimeter. Log Audit Platform runs self-hosted:

  • Backend: Spring Boot 3 + Java 17+
  • Frontend: Vue 3 admin UI, embedded in the build
  • Storage: PostgreSQL
  • Shipping: a single runnable JAR + Docker Compose

No vendor backend, no telemetry pipe, no API calls home after activation. It runs in your VPC, on-prem, or air-gapped. For teams that can't use a cloud SIEM for regulatory reasons, that's the whole point.


7. Pricing: one-time license, not a per-seat SaaS tax

SIEM pricing scales with ingest volume and seats — exactly the metrics that go up when you start taking compliance seriously. We priced it as a one-time license:

  • Single — $199 (one instance)
  • Business — $699 (up to 5)
  • Enterprise — $2,499 (full source + white-label + OEM)

Optional annual maintenance for updates. No per-seat tax, no surprise overage bills right before your audit.


Try it

If you're preparing for a SOC 2, ISO 27001, or GDPR audit and want an audit log that auditors can verify independently, take a look:

https://logaudit.toolsder.com

I'd genuinely like feedback from security engineers and compliance folks — what logging controls have been the biggest pain in your audits? What would make you trust a self-hosted log like this one?


Qin Kang — independent developer, building self-hosted compliance tooling.

Top comments (0)