Security & Trust

Audit Logging

How Versus records who did what — a searchable activity log across every workspace, plus tamper-evident, hash-chained audit trails in the sensitive subsystems (Vault, Versus Desk change management, privileged sessions) whose integrity you can verify on demand.

Versus records who did what, to which resource, and when across the platform. There are two complementary layers, used for two different jobs:

  • A searchable activity log — a flat, queryable record of actions across every workspace, for day-to-day "who changed this?" investigation and reporting.
  • Tamper-evident hash chains — append-only, cryptographically linked trails in the subsystems where integrity matters most (the Secret Vault, Versus Desk change management, and privileged sessions), whose integrity you can verify on demand.

The activity log answers what happened. The hash chains additionally prove the record hasn't been altered since.


The activity log

The activity log is a single append-only table of Audit records. Anything security-relevant an operator or the platform does — creating and updating inventory, toggling rules, running upgrades, taking backups, signing in, vault operations — lands here as one row.

Each record carries:

FieldMeaning
userThe actor — a username, or system for platform-initiated actions.
actionOne of create, update, delete, toggle, upgrade, backup, login, other.
resource_typeThe kind of object touched, e.g. vault_secret, a device, a rule.
resource_idThe object's identifier, where one applies.
resource_nameA human-readable label for the object.
detailsA JSON blob of action-specific context.
ip_addressThe source address, where available.
timestampWhen it happened (set at write time, never editable).

Reading the log over the API

The log is exposed read-only — there is no API to create, edit, or delete an audit row by hand. Fetch it with a standard authenticated request (see Running Workflows via the API for how to obtain a bearer token):

GET /api/audit-log/
Authorization: Bearer eyJhbGc…

Results are ordered newest-first and can be narrowed with query filters and full-text search:

GET /api/audit-log/?action=delete&resource_type=vault_secret
GET /api/audit-log/?user=svc-automation
GET /api/audit-log/?search=bigip-pair-1
FilterMatches on
actionExact action type.
resource_typeExact resource kind.
userExact actor.
searchSubstring of resource_name or user.

Because the endpoint is tenant-scoped, a caller only ever sees audit rows for their own tenant — the same row-level isolation that guards the rest of the platform (see Platform Architecture) applies to the audit log itself.


Tamper-evident hash chains

For the subsystems that hold secrets, gate change, or broker privileged access, a flat log isn't enough — you also need to prove the record wasn't quietly edited after the fact. Versus does this with hash-chained audit events.

The design is the same everywhere it appears:

  • Every event has a monotonic sequence number seq and stores the hash of the previous event as prev_hash.
  • Each event's own hash is a SHA-256 digest computed over its contents and that prev_hash, so every row is cryptographically bound to the one before it.
  • Events are append-only. Nothing in the platform updates or deletes a past row.

The consequence: altering or removing any historical event changes its hash, which breaks the link every later event depends on. A verification pass walks the chain in order, recomputes each hash, and reports the first sequence number where the stored value and the recomputed value disagree — pinpointing exactly where the tampering occurred.

Four subsystems maintain chains, each scoped to its own domain rather than a single global ledger.

Vault audit chain

Every operation against the Secret Vault writes to the chain — reads included. The recorded actions cover the full lifecycle of a secret:

ActionWhen it fires
write, read, delete, destroySecret created, accessed, soft-deleted, hard-destroyed.
lease, renew, revokeDynamic/leased credential granted, extended, revoked.
rotate, rotation_failedSecret rotation succeeded or failed.
checkout, checkin, force_releaseExclusive credential check-out lifecycle.
reveal_request, reveal_approved, reveal_denied, reveal_consumedThe break-glass reveal-approval flow.
enroll, unenrollA device credential brought under (or removed from) vault management.

A vault operation writes to both layers at once: it appends a flat Audit row (so it shows up in the activity log and reports alongside everything else) and a hash-chained VaultAuditEvent (so its integrity is independently provable). Each chained event records the actor, the action, the mount and path acted on, and an action-specific details payload — never the secret material itself. This is the trail behind the "day in the life of a secret" story: from enrollment through every read and rotation to destruction.

Versus Desk change audit chain

Versus Desk keeps a hash-chained trail of the events that move a ticket through its lifecycle — the record an auditor asks for when reviewing a change. Event types include state transition, assignment, comment, approval_decision, SLA sla_warn / sla_breach, knowledge-base kb_publish, and external sync. Each event's hash is computed as:

hash = SHA-256( prev_hash + canonical_json(payload) )

where canonical_json is a stable, key-sorted serialization, so the same payload always hashes the same way. This gives you a defensible chain of custody for approvals and change execution that ties into the workflow engine's own durable run records.

Privileged session chain

Every privileged session the platform brokers — SSH or HTTPS, where the credential is injected by Versus and never shown to the operator — carries its own per-session hash chain. Events capture the session lifecycle: connect, inject, command, proxy, approve, terminate, close, and rotate (the rotate-on-close that swaps the credential once the session ends). Because the chain is scoped to a single session, you can hand over a self-contained, verifiable record of exactly what happened during one privileged access episode.

Firewall automation records

The firewall-automation subsystem records an audit entry for each access-request change with a before_hash and after_hash — digests of the rule state on either side of the change. This is a point-in-time integrity check on what was changed (proving the before/after state), distinct from the append-only chains above that prove the sequence of events is intact.


Verifying integrity

Each chain exposes a verification routine that walks it in sequence order, recomputes every hash, and reports whether the chain is intact.

For Versus Desk, verification is a first-class API action, gated behind the itsm.manage permission:

GET /api/itsm/audit/verify/
Authorization: Bearer eyJhbGc…
200 OK
{ "ok": true, "message": "chain verified" }

If a row had been altered or removed, ok is false and message names the exact break, e.g. hash mismatch at seq=418: recomputed … != stored ….

For privileged sessions, the verification result is returned inline whenever you read a session's events, so the integrity check travels with the evidence:

GET /api/psm/sessions/{id}/events/
200 OK
{
  "events": [ … ],
  "chain": { "events": 12, "intact": true, "broken_at": null }
}

The vault chain's verification routine returns the same shape — { "events": N, "intact": true|false, "broken_at": null|<seq> } — walking every VaultAuditEvent from the first sequence number and stopping at the first row whose stored hash or back-link doesn't match.


How an operator uses it

  • Investigate a change. Filter /api/audit-log/ by resource_type, user, or a search term to find every action against a device, rule, or secret, then read the details payload for the specifics.
  • Attribute automation. Runs triggered by a service account are attributed to that account. Use a dedicated service account for automation, scoped by RBAC, so its actions are cleanly separable from human ones in the log.
  • Prove integrity for an audit. When a reviewer needs assurance that the change or secret-access record is complete and unaltered, run the relevant chain's verify action and hand over the intact: true result together with the events.
  • Report across the estate. Because the activity log lives in the same relational system of record as inventory and workflow history, audit data shows up in the same dashboards, searches, and exports as everything else — cloud and on-prem edges included.

How it fits the platform

Audit is one of the platform's secure-by-default guarantees, not an add-on you enable. It sits across the layers described in Platform Architecture:

  • The application core is the single choke point for writes, so every state change flows through one place that can record it — the UI, integrations, and automation all produce the same audit trail.
  • Tenant isolation (row-level security) scopes audit reads to a tenant, so the log can't leak cross-tenant activity.
  • The collector plane reaches your devices outbound-only, and the actions collectors carry out are attributed and recorded through the same subsystems (see Collector Security).
  • The same trails exist in cloud and self-hosted deployments — it's the same software, so a self-hosted appliance produces the same tamper-evident record a managed tenant does.

The activity log gives you fast, searchable answers; the hash chains give you defensible, verifiable proof. Together they let you reconstruct — and stand behind — the history of change across your network estate.


Related