Audit Vault Documentation
Complete guide to installing, configuring, and using Audit Vault for tamper-evident audit logging in Jenkins.
Installation
Audit Vault can be installed in two ways:
Option 1: Upload HPI File
- Download the latest
audit-vault.hpifile from your dashboard - Navigate to Manage Jenkins → Plugins → Advanced Settings
- Under "Deploy Plugin", click "Choose File" and select the HPI file
- Click "Deploy" to install the plugin
Option 2: Manual Installation
-
Copy the
audit-vault.hpifile to your Jenkins plugins directory:cp audit-vault.hpi $JENKINS_HOME/plugins/ - Restart Jenkins to load the plugin
Note
Audit Vault uses SQLite for local event storage. The database file is created automatically
at $JENKINS_HOME/audit-vault/events.db.
Quick Start
Get audit logging running in minutes:
1. Activate Your License
Navigate to Manage Jenkins → System → Audit Vault. Enter your license key and click "Validate License".
2. Enable Event Capture
Check "Enable Audit Vault" and select which event categories to capture (authentication, jobs, credentials, system).
3. Configure an Export Destination (Optional)
Enable one or more of S3 (or an S3-compatible store), a filesystem directory, SFTP, or Azure Blob Storage under Export Destinations below, then click each destination's "Test" button to verify. The export interval (default: 60 minutes) is shared by every destination.
4. Save Configuration
Click "Save". Audit Vault immediately begins capturing events and storing them in the local SQLite database.
5. View the Dashboard
Navigate to Audit Vault in the Jenkins sidebar to view event stats, export status, and chain integrity.
Requirements
- Jenkins Version: 2.426.x LTS or later
- Java Version: Java 17 or later
- Network: HTTPS connectivity for license validation
- Disk Space: SQLite database grows with event volume (approximately 1 KB per event)
- S3 Export (optional): AWS credentials with
s3:PutObjectpermission on the target bucket (an S3-compatible endpoint override works the same way, for GCS, MinIO, Cloudflare R2, Wasabi or on-prem Ceph) - Filesystem Export (optional): an export directory (local disk or mounted network share) that already exists and is writable by the Jenkins process; the plugin never creates it
- SFTP Export (optional): the SSH Credentials, Bouncy Castle API and Apache MINA SSHD API plugins; an SSH key credential; and the server's host key(s) in Known Hosts (mandatory -- SFTP export does not run without them)
- Azure Blob Export (optional): the Azure SDK API plugin; an existing container; and a Secret-text credential holding a SAS token or connection string
Global Settings
Configure Audit Vault in Manage Jenkins → System → Audit Vault.
Enable Audit Vault
Master toggle to enable or disable all event capture. When disabled, no new events are recorded but existing data is preserved.
License Key
Your ozen_av_ license key. Click "Validate License" to activate. The plugin requires
a valid license to capture events.
Event Capture Configuration
Control which categories of events are captured. Each toggle controls a group of related event types.
Capture Toggles
- Authentication Events: Login, logout, failed authentication attempts
- Job Events: Job creation, modification, deletion, copying, renaming
- Build Events: Build started, completed, deleted (includes trigger cause and result)
- Credential Events: Credential creation, modification, deletion, access
- System Events: Plugin changes, configuration modifications, node activity, security realm changes
Tip
For compliance purposes, enable all event categories. You can always filter events by category when querying or exporting.
Export Destinations
Audit Vault can export audit events to any combination of four destinations: Amazon S3 (or an S3-compatible store), a filesystem directory, an SFTP server, or Azure Blob Storage. Enable each one independently. All four write the same NDJSON content with the same date-based partitioning, and the export interval (default: 60 minutes, minimum: 5) is shared by every destination.
Important
Events are buffered locally in SQLite. With more than one destination enabled, an event only counts as exported, for retention purposes, once every currently enabled destination has confirmed delivery. No events are lost during network outages or export failures -- they stay queued locally until the destination recovers.
S3 Export
Schedule exports to Amazon S3 for long-term storage and SIEM integration.
- Bucket Name: Target S3 bucket (must already exist)
- Region: AWS region (e.g.,
us-east-1) - Key Prefix: Optional path prefix for exported files (e.g.,
jenkins/audit/) - Access Key ID: AWS access key with S3 write permissions
- Secret Access Key: Corresponding AWS secret key
- Enable Encryption: Server-side AES-256 encryption on uploaded objects -- S3-only; the other three destinations have their own security model, described under each below
Required IAM Permissions
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:PutObject"
],
"Resource": "arn:aws:s3:::your-bucket-name/*"
}
]
} S3 Path Structure
Events are exported with date-based partitioning for efficient querying:
{prefix}/yyyy/MM/dd/HH/audit-{timestamp}-{count}.ndjson Example: jenkins/audit/2026/02/17/14/audit-1708182000-207.ndjson
S3-Compatible Endpoint (Optional)
An optional endpoint URL points the same S3 client at an S3-compatible store instead of AWS S3 itself, using the AWS SDK's own endpoint-override support (no new dependency). Leave it blank to use AWS S3, unchanged. This covers GCS via its S3-interoperability API with HMAC keys (not the native Google Cloud Storage API; there is no native GCS destination), MinIO and on-prem Ceph (check Force Path-Style Access, since these typically don't support virtual-hosted-style DNS), Cloudflare R2, and Wasabi. For GCS and R2, leave Enable Encryption unchecked: GCS and R2 both encrypt at rest by default, and R2 rejects the S3 server-side-encryption header outright. Changing the endpoint does not re-export events already written to the previous target.
Testing the Connection
Click "Test S3 Connection" to verify your credentials and bucket (or custom endpoint) access. The test uploads a small test object and confirms write permissions.
Filesystem Export
Writes each batch as an NDJSON file to a directory on the controller -- a local disk or a mounted network share -- for air-gapped controllers and for log shippers (Splunk Universal Forwarder, Filebeat, Fluent Bit, Datadog Agent) that read a directory.
- Export Directory: an absolute path that must already exist and be writable by the Jenkins process. Audit Vault checks this before every export and never creates the directory itself, so a mistyped path fails visibly instead of writing somewhere else. It can't tell whether a network share is actually mounted at that path.
Click "Test Export Directory" to confirm the path exists, is a directory, and is writable (it
writes nothing). Each file is written through an atomic temp-file-plus-rename (Jenkins core's AtomicFileWriter), with a .meta.json sidecar file carrying the same checkpoint an S3 export stores
as object metadata.
SFTP Export
Uploads each batch to a directory on an SFTP server, for on-premises and air-gapped archives.
- Host, Port, Remote Directory: the SFTP server and a target directory that must already exist
- Credentials: an SSH Username with private key credential (public-key login only; passphrase-protected keys work)
- Known Hosts: the server's pinned host key(s), collected with
ssh-keyscan.ssh-keyscanitself does not authenticate the key it returns; it will happily hand back an attacker's key during a man-in-the-middle attack. Before pasting its output into Known Hosts, verify every key returned through a trusted out-of-band channel. Either collect only the key type you need by runningssh-keyscan -t ed25519 hostname, then verify its fingerprint, or runssh-keyscan hostname(which may return multiple key types) and verify the fingerprint of each one before saving. Runssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub(or the equivalent for your key type) directly on the SFTP server, or get the fingerprints from your infrastructure team, and confirm they match before saving. Host-key verification is mandatory: with no Known Hosts entered, SFTP export does not run at all, and a server whose key isn't listed is refused before any login or upload attempt.
Click "Test SFTP Connection" to verify the host key, log in, and confirm the remote directory
exists (it writes nothing, so it can't prove the account can write there; the first export
does). Uploads go to a temporary name, flushed to disk when the server supports the OpenSSH
fsync extension (most modern SFTP servers, including OpenSSH itself, do), then renamed
into place, with the same .meta.json checkpoint sidecar as filesystem export.
Azure Blob Export
Uploads each batch as one NDJSON block blob to an existing Azure Blob Storage container.
- Container, Path Prefix: the target container (must already exist; Audit Vault
never creates it) and an optional blob-name prefix (default
jenkins/audit/) - Credentials: a Secret-text credential holding a SAS token (Create and Write permissions, HTTPS only recommended) or a storage-account connection string
Click "Test Azure Blob Connection" to validate the credential: it sends one read-only request
for a blob name that never exists and writes nothing. The checkpoint is stored as blob
metadata in the same request as the upload, so there's no separate sidecar file; any SAS token
or account key in a logged failure is shown as [redacted].
Event Types
Audit Vault captures 35+ event types across 7 categories:
Authentication
USER_LOGIN- Successful user authenticationLOGIN_FAILED- Failed authentication attemptUSER_LOGOUT- User logout
Authorization
PERMISSION_CHANGED- Permission modificationSECURITY_REALM_CHANGED- Security realm configuration change
Job Activity
JOB_CREATED- New job createdJOB_MODIFIED- Job configuration changedJOB_DELETED- Job deletedJOB_COPIED- Job copied from anotherJOB_RENAMED- Job renamed
Build Activity
-
BUILD_STARTED- Build execution started (includes trigger cause) -
BUILD_COMPLETED- Build finished (includes result: SUCCESS, FAILURE, etc.) BUILD_DELETED- Build record deleted
Credential Events
CREDENTIAL_CREATED- New credential addedCREDENTIAL_MODIFIED- Credential updatedCREDENTIAL_DELETED- Credential removedCREDENTIAL_ACCESSED- Credential accessed by a job or user
System Events
-
PLUGIN_INSTALLED/PLUGIN_UPDATED/PLUGIN_REMOVED- Plugin lifecycle CONFIG_CHANGED- System configuration modified-
NODE_ADDED/NODE_REMOVED/NODE_ONLINE/NODE_OFFLINE- Node activity SECURITY_CONFIG_CHANGED- Security settings modified
Severity Levels
Each event type has a default severity:
- INFO - Normal operations (logins, builds, config reads)
- WARNING - Notable actions (permission changes, credential access)
- ERROR - Failed operations (login failures, export failures)
- CRITICAL - Security-sensitive events (security realm changes)
Tamper-Evident Logging
Every audit event includes cryptographic integrity guarantees.
SHA-256 Checksums
Each event's checksum is computed from its core fields:
SHA-256(id | timestamp | eventType | actor | resourceType | resourceId | summary | prevHash) Hash Chaining
Events are linked in a chain where each event includes the checksum of the previous event (prevHash). This creates a verifiable chain of custody:
Event 1: checksum=abc123, prevHash=0000...0000 (genesis)
Event 2: checksum=def456, prevHash=abc123
Event 3: checksum=ghi789, prevHash=def456 If any event is modified or deleted, the chain breaks and integrity verification will detect the tampering.
Genesis Hash
The first event in the chain uses a special genesis hash (0000...0000) as its prevHash, establishing the start of the chain.
Integrity Verification
Audit Vault verifies the hash chain automatically, incrementally, in the background -- there is no manual "run now" click. A full walk of every event runs once, at Jenkins startup (and after a storage re-initialization), to bound how long tampering further back in the chain could go undetected.
How It Works
After the startup walk, each later maintenance pass:
- Re-verifies the previously-checkpointed chain head plus every event captured since the last pass
-
Re-verifies
prevHashand the recomputed checksum for a bounded, rolling slice of older events, so history behind the checkpoint keeps getting re-checked over time without re-walking the whole log on every pass - Re-walks the entire chain again roughly every 24 passes once the log passes 10,000 events (below that, every pass re-verifies the whole chain, since it's still cheap to)
- Reports any broken links or corrupted events, identifying the specific event
Verification Result
- Valid: All events verified so far, chain is intact
- Failed: Specific event where the chain breaks is identified
Tip
The Audit Vault dashboard's Log Integrity box shows the latest check's result, when it ran, and a separate "Last full re-verification" time for the most recent complete walk -- useful for confirming a walk has covered a given point in history before relying on it.
Dashboard
Access the Audit Vault dashboard from the Jenkins sidebar at Audit Vault.
Dashboard Sections
- License Status: Current license state and expiration
- Event Statistics: Total events, unexported count, events by category and severity
- Chain Integrity: Result of the last incremental check, when it ran, and the time of the last full re-verification
- Export Status: Per-destination export health, last export time, event counts
- Recent Events: Table of the 50 most recent audit events with type, actor, summary, and timestamp
Export Format
Events are exported in NDJSON (Newline Delimited JSON) format, one event per line. This format is compatible with most SIEM tools including Splunk, Datadog, and Elasticsearch.
Event JSON Schema
{
"id": "a1b2c3d4",
"timestamp": "2026-02-17T14:30:00Z",
"eventType": "USER_LOGIN",
"category": "AUTHENTICATION",
"severity": "INFO",
"actor": "admin",
"actorIp": "10.0.1.50",
"resourceType": "user",
"resourceId": "admin",
"resourceName": "admin",
"summary": "User admin logged in",
"details": "Authentication via password",
"metadata": {},
"checksum": "sha256:abc123...",
"prevHash": "sha256:def456..."
} SIEM Integration
Point your SIEM tool at the S3 bucket path to ingest audit events. The date-based partitioning supports efficient time-range queries:
- Splunk: Use the S3 input with sourcetype
_json - Datadog: Configure an S3 log source with JSON parsing
- Elasticsearch: Use Logstash S3 input with JSON codec
Licensing
Activating Your License
- Purchase a subscription from the product page
- Copy your license key from the dashboard
- In Jenkins, navigate to Manage Jenkins → System → Audit Vault
- Enter your license key and click "Validate License"
License Validation
Audit Vault validates your license periodically (every 24 hours). If the license server is unreachable, a 72-hour grace period allows continued operation.
Unlicensed Behavior
Without a valid license:
- Event capture is disabled
- Existing events remain in the database and can be viewed
- Already-configured export destinations keep running on schedule -- with capture stopped there's nothing new to send, but any backlog not yet exported still goes out
- A warning banner is shown to admins
FAQ
How much disk space does Audit Vault use?
Each event is approximately 1 KB in the SQLite database. A moderately active Jenkins instance generating 1,000 events/day would use about 1 MB/day or 365 MB/year. Exported events can be purged from the local database to reclaim space.
What happens if Jenkins crashes during event capture?
SQLite with WAL (Write-Ahead Logging) mode ensures durability. Events that were committed to the database before the crash are preserved. The hash chain resumes from the last committed event on restart.
Can I export to destinations other than S3?
Yes. Besides S3 (any S3-compatible store works too, including MinIO, DigitalOcean Spaces, Backblaze B2, Cloudflare R2, Wasabi, and GCS via its S3-interoperability API -- not a native GCS destination), Audit Vault can export to a filesystem directory or mounted network share, an SFTP server with mandatory host-key verification, or an Azure Blob Storage container. Enable any combination; all four write the same NDJSON content and date-partitioned layout.
Does Audit Vault capture build log contents?
No. Audit Vault captures metadata about builds (started, completed, result, trigger cause) but never captures build log contents. This keeps event sizes small and avoids storing sensitive output.
What data leaves my Jenkins instance?
Only two types of outbound communication:
- License validation: License key, product identifier, controller identifier (a pseudonymous ID; or the controller URL when a request does not include one, as with older plugin versions), and plugin version sent to
ozenops.dev. As with any web request, our server also sees your request's source IP, which we retain for rate limiting and audit (see the privacy policy). - Export: Audit events sent to each export destination you configure and enable -- your own S3 bucket (or S3-compatible store), a filesystem directory or network share, an SFTP server, or an Azure Blob container
No build-content telemetry, analytics, or usage tracking is ever sent to OzenOps: job data, build logs, and credentials are never transmitted to us. (If you enable export, audit events, which include job/build metadata, go to your own configured destination(s), as described above; that path never touches OzenOps servers either.)
How do I verify integrity of exported events?
Every export carries a checkpoint: the batch's own sequence range plus the audit chain head (sequence number and SHA-256) the plugin read when it exported the batch. S3 exports carry this as object metadata; filesystem and SFTP exports carry the same values in a .meta.json file beside each export file; Azure Blob exports carry it as blob metadata.
The plugin's README ships a documented check-archive.sh script that checks a downloaded export against a copy of the controller's database and reports two separate results: a Head check (whether your database's chain still passes through the recorded head) and a Body check (whether every line of the export matches its database row). A confirmed head is never presented as a verified body, or vice versa.
Changelog
Recent Updates (2026-10-23)
- Chain integrity verification is now incremental: a full walk of every event runs once, at Jenkins startup, and each later maintenance pass re-verifies the checkpointed chain head, every event captured since, and a rolling slice of older events, re-walking the whole chain again roughly every 24 passes once the log passes 10,000 events.
-
Every S3 export object now carries its sequence range and the audit chain head as object
metadata, so a downloaded archive can be checked against a copy of the controller's database
with the documented
check-archive.shscript (see the FAQ and "Export Destinations" above). Filesystem and SFTP exports carry the same checkpoint in a.meta.jsonsidecar file; Azure Blob exports carry it as blob metadata. - Three new export destinations: a filesystem directory or mounted network share, an SFTP server (mandatory host-key verification), and Azure Blob Storage. An optional S3-compatible endpoint override also lets the existing S3 destination target GCS, MinIO, Cloudflare R2, Wasabi or on-prem Ceph.
Version 1.0.0
Initial Release
- 35+ event types across 7 categories
- SHA-256 tamper-evident checksums with hash chaining
- SQLite local storage with WAL mode
- Automated S3 export with date-based partitioning
- NDJSON export format for SIEM compatibility
- Server-side AES-256 encryption for S3 exports
- Real-time audit dashboard
- One-click chain integrity verification
- Configurable event capture per category
- License management with 72-hour grace period