Skip to content

Compliance

This section describes TKeeper compliance-oriented controls:

  • Audit logging and verification: signed, tamper-evident records for security-relevant operations.
  • Asset inventory: machine-readable inventory of managed keys for oversight and reporting.

Regulatory packet (KMS suitability overview):

https://cdn.exploit.org/tkeeper-regulatory.pdf

Audit logging and verification

Audit logging is an enforceable control in TKeeper. When audit logging is enabled, every security-relevant operation emits a signed audit record. If no configured sink can accept the record at the time of the operation, the operation is denied.

Enabling audit logging

keeper {
  audit {
    enabled = true
  }
}

Operational rule: - enabled = false: audit records are not produced; sinks are not required. - enabled = true: at least one sink must be functional; otherwise secured operations are denied.

Log format

Audit logs are emitted as NDJSON (.ndjson): one JSON object per line.

Each line is a SignedLine with two fields:

  • event: JSON object describing the audit event
  • signature: Base64-encoded Ed25519 signature over the exact UTF-8 bytes of the event object

Example (schema-level):

{
  "event": { "...": "..." },
  "signature": "base64(ed25519(event_bytes))"
}

AuditEvent fields

event contains structured data about what happened. Not every field is present on every record; unused sections may be null or absent depending on the event type.

Common fields:

  • id: unique event identifier
  • peerId: keeper instance that emitted the record
  • integrityKeyVersion: version of the integrity signing key used for this record
  • timestamp: epoch milliseconds (UTC)
  • event: event category identifier (for example event.frost.init)
  • auth.subject: authenticated subject (if available)
  • context.sid: session identifier for multi-party operations
  • request.method, request.path, request.remoteAddress: HTTP request context
  • crypto.algo, crypto.kid, crypto.curve: cryptographic context (algorithm, key id, curve)
  • digest.purpose: label for the hashed payload (for example audit or requestBody)
  • digest.hmacKeyVersion: version of the local HMAC key used to compute the body hash
  • digest.bodyHash.alg: HMAC_SHA256
  • digest.bodyHash.value64: Base64-encoded HMAC-SHA256 of the request body (request bodies are not persisted)
  • outcome.statusCode, outcome.error, outcome.details: HTTP outcome and error details (including failures)
  • imposters: Malicious nodes detected during this request
  • dead: Dead nodes detected during this requests

Integrity key and rotation

Each SignedLine is signed using an Ed25519 integrity key. The signing key version is recorded in integrityKeyVersion.

Integrity key rotation is performed via the Integrity API family. On rotation: - TKeeper generates a new integrity key and increments the version. - Prior integrity key versions remain available for verification of existing audit records.

Audit sinks

A sink is a destination that receives SignedLine records. TKeeper supports:

  • File sink (keeper.audit.file)
  • Socket sink (keeper.audit.socket)

Sinks can be enabled independently or together. When keeper.audit.enabled = true, at least one sink must be able to accept records.

File sink

The file sink writes SignedLine records as NDJSON to local files and supports rotation and retention controls.

keeper {
  audit {
    file {
      directory = "audit"
      extension = "ndjson"
      max-file-size-bytes = 67108864
      prefix = "audit"

      # Optional
      roll-every = 1h

      max-files = 10
      retention-days = 30
      gzip = false
      fsync = false
    }
  }
}
Key Meaning Default
directory Output directory. audit
extension Filename extension. ndjson
max-file-size-bytes Rotate when file exceeds this size. 64 MiB
prefix Prefix for rotated file names. audit
roll-every Time-based rotation interval. unset
max-files Maximum number of rotated files to keep. 10
retention-days Maximum age (days) for rotated files. unset
gzip Compress rotated files. false
fsync Call fsync() after writes. false

Socket sink

The socket sink streams SignedLine records over a persistent TCP connection, optionally protected with TLS.

keeper {
  audit {
    socket {
      host = "collector.example.com"
      port = 443
      connect-timeout-millis = 2000
      read-timeout-millis = 2000
      tcp-no-delay = true
      keep-alive = true
      so-linger-seconds = 0

      tls {
        protocols = ["TLSv1.3", "TLSv1.2"]
        verify-hostname = true

        trust {
          mode = "system"   # or "custom"
          path = "/etc/tkeeper/truststore.jks"
          password = "change-me"
          type = "JKS"
        }

        spki-pins = ["base64(spki)"]

        client {
          keystore-path = "/etc/tkeeper/client.p12"
          keystore-password = "change-me"
          keystore-type = "PKCS12"
        }
      }
    }
  }
}
Key Meaning Default
host / port Collector address. localhost / 443
connect-timeout-millis TCP connect timeout. 2000
read-timeout-millis Read timeout. 2000
tcp-no-delay Disable Nagle’s algorithm. true
keep-alive Enable TCP keep-alive. true
so-linger-seconds Linger time on close. 0
tls.protocols Allowed TLS versions. ["TLSv1.3","TLSv1.2"]
tls.verify-hostname Verify TLS hostname. true
tls.trust.* Trust configuration (optional store). unset
tls.spki-pins Base64 SPKI pins for certificate pinning. unset
tls.client.* Client keystore for mTLS. unset

Verification endpoints

TKeeper exposes verification endpoints for SignedLine records:

  • POST /v1/keeper/audit/verify (single record)
  • POST /v1/keeper/audit/verify/batch (multiple records)

Required permission:

  • tkeeper.audit.log.verify

Verification checks:

  1. Verify the detached Ed25519 signature using the integrityKeyVersion referenced by the event.
  2. If the record includes a request-body digest, recompute and verify the HMAC body hash.

Peer constraint:

  • The keeper that emitted a record holds the HMAC key material referenced by peerId / digest.hmacKeyVersion.
  • For digest verification, submit verification requests to the same keeper identified by peerId in the audit record.

Asset inventory

Tip

You can also access Asset Inventory via TKeeper Control Plane available at /ui.

Asset inventory provides a machine-readable snapshot of keys and their lifecycle state. This is designed for compliance reporting, operational oversight, and internal governance.

Endpoint

  • GET /v1/keeper/compliance/inventory

Required permission:

  • tkeeper.compliance.inventory

Query parameters

Parameter Meaning Default
logicalId Filter by key logicalId. unset
historical Include historical entries. Logical ID should be specified false
lastSeen Pagination cursor from the previous response. unset
limit Maximum items to return (capped at 200). 200
assetOwner Asset Owner filter passed during generation unset

Response overview

The response is a paginated snapshot and typically includes:

  • snapshot metadata (generation time, emitting peer)
  • cluster snapshot fields (threshold, totalPeers)
  • items[] with per-key information (logical id, status, current generation, timestamps, policy if set)

Inventory is intended to be safe for reporting workflows. It describes key metadata and state and does not expose private key material.