v0.30.0¶
Release Date: 2026-10-29
A release that writes SystemForge's security events as OCSF:
- OCSF security events.
contract/audit/ocsfauditmaps every security event to an OCSF 1.10.0-dev event class and writes it as one JSON object per line to a writer the host names, typically a file opened for appending, for a security data lake or SIEM that ingests OCSF. - Several emitters at once.
audit.NewMultiEmitterhands every event to each of its emitters, so a deployment can keep the log of security events and write OCSF too.
It also sanitizes the client's User-Agent in every security event, in the
log as well as in OCSF, leaving it out when it looks like it holds an email
address or a credential.
It adds no breaking change. Nothing is written as OCSF until a host passes
the emitter, for example as systemauthsvc.Options.AuditEmitter.
Highlights¶
- Every event type mapped. Sign-ins, sign-outs, token refusals, revocations and replays are Authentication events; account, email and privilege changes are User Management; organization membership is Group Management; keys, connections, SCIM tokens, sign-up codes and invites are Entity Management; signing-key loading and production waivers are Application Lifecycle. An event type SystemForge adds later is still written, as an OCSF Base Event. The mapping lists every class and activity.
- Valid OCSF. A test validates the output of every event type, with
success and failure variants, strictly against the schema embedded in
github.com/grokify/ocsf-schema-go. Events carry the schema version1.10.0-devinmetadata.version, the development version of OCSF 1.10; check that a destination accepts it. - Fields a lake can filter on. The deployment's name is in
metadata.reporter.name, the organization inmetadata.tenant_uid, the event type inmetadata.event_codeand the request ID inmetadata.correlation_uid, beside the principal's ID, the client address and the user agent.
Security¶
- Only IDs and addresses identify people. Names, email addresses,
session tokens, tokens, token and code prefixes, codes, proofs and
free-text reasons are left out of every field,
unmappedincluded. A revoked managed-principal session is named by its record UUID insession.uid, which is no credential. Event details reach the output only through an allowlist for each event type, and only as codes, UUIDs, booleans, integers and times. The tests proving no token or secret reaches a log or event now run this emitter too. - The
User-Agentis sanitized. A client can put anything in it, soaudit.SanitizeUserAgentremoves control characters, leaves out aUser-Agentthat then looks like it holds an email address or a credential, and cuts any other to 512 bytes. The OCSF emitter and the log emitter (audit.NewLogEmitter) both record only the sanitized value. The check is a heuristic for the common shapes, not a guarantee against every piece of personal data a client could send. - Severity follows the signal. A refresh token or authorization code
replay is High severity with
is_alertset, granting platform admin is High, and a production waiver at startup is Medium.
Delivery¶
Emitnever blocks, never logs and never fails the request. It encodes the event and queues the line in a bounded buffer (1024 lines by default) that one goroutine writes.- When the buffer is full the event is dropped and counted (
Dropped); a reporter goroutine logs the count once a minute and onClose, so a slow log destination cannot hold up a request. Write failures, short writes included, are counted (WriteFailures) and logged at most once a minute. - A
Writethat fails part-way, as on a full disk, loses only its own line: the next line starts on a new line, so every following line is whole JSON. Closestops accepting events, writes those queued, flushes the writer and syncs a file. It does not close the writer.- Rotation is the host's job. Rotate by renaming, with a writer that
reopens its file on
SIGHUP, withpostrotatewaiting for the reopen anddelaycompresswhen compressing;copytruncatecan lose events written between its copy and its truncation.
See OCSF Security Events for wiring with an append-mode file and the full list of attributes.
Upgrading¶
Nothing changes for an existing deployment. To write OCSF events, open a
file for appending, pass ocsfaudit.New(file, ocsfaudit.Options{...}) as
the audit emitter (combined with the existing one through
audit.NewMultiEmitter to keep both), and call Close on shutdown before
closing the file.
The log emitter now leaves out a User-Agent that holds an email address
or a credential-like value; log queries that matched such values in
context.user_agent find nothing.
Dependencies¶
- Adds
github.com/grokify/ocsf-schema-gov0.2.0.