Documentation
¶
Overview ¶
Package audit implements VORTEX's tamper-proof audit log (build plan M3.6): an append-only, HMAC-SHA256 hash-chained record of security-relevant events. Each entry's hash covers the previous entry's hash, so removing, reordering, or modifying any entry breaks the chain and is detected by Verify. It uses only the standard library (crypto/hmac, crypto/sha256).
Index ¶
- Constants
- func ExportCSV(log *Log, filter QueryFilter, w io.Writer) error
- func ExportJSON(log *Log, filter QueryFilter, w io.Writer) error
- func ExportSplunk(log *Log, filter QueryFilter, w io.Writer) error
- func ExportSyslog(log *Log, filter QueryFilter, w io.Writer) error
- type ComplianceReport
- type Entry
- type Log
- func (l *Log) Append(_ context.Context, actor, action, resource string, detail map[string]any) error
- func (l *Log) Archive() (string, error)
- func (l *Log) ArchiveIfOver(limit int64) (string, bool, error)
- func (l *Log) Query(filter QueryFilter) ([]Entry, error)
- func (l *Log) Rekey(newKey []byte) error
- func (l *Log) Verifies() bool
- func (l *Log) Verify() error
- type QueryFilter
Constants ¶
const ( ArchiveThreshold = 100 * 1024 * 1024 // 100MB ArchiveRetention = 2 * 365 * 24 * time.Hour )
Archival policy (build plan M19): the live log is rotated into a gzipped archive once it exceeds ArchiveThreshold, and archives older than ArchiveRetention are pruned.
Variables ¶
This section is empty.
Functions ¶
func ExportCSV ¶
func ExportCSV(log *Log, filter QueryFilter, w io.Writer) error
ExportCSV writes the filtered entries as CSV with a header row. The detail map is JSON-encoded into a single column.
func ExportJSON ¶
func ExportJSON(log *Log, filter QueryFilter, w io.Writer) error
ExportJSON writes the filtered entries as a single JSON array to w.
func ExportSplunk ¶
func ExportSplunk(log *Log, filter QueryFilter, w io.Writer) error
ExportSplunk writes the filtered entries in Splunk HEC JSON format, one event per line: {"time":<epoch>,"event":{...entry fields...}}.
func ExportSyslog ¶
func ExportSyslog(log *Log, filter QueryFilter, w io.Writer) error
ExportSyslog writes the filtered entries in RFC 5424 syslog format, one line per entry. VORTEX audit events use facility 13 (log audit) and severity 6 (informational), giving PRI = 13*8 + 6 = 110.
Types ¶
type ComplianceReport ¶ added in v0.3.0
type ComplianceReport struct {
Period string `json:"period"`
TotalEvents int `json:"total_events"`
ChainValid bool `json:"chain_valid"`
EventsByActor map[string]int `json:"events_by_actor"`
EventsByAction map[string]int `json:"events_by_action"`
SecurityEvents []Entry `json:"security_events"` // auth failures, policy denials
AdminActions []Entry `json:"admin_actions"` // config changes, secret/key/namespace ops
GeneratedAt time.Time `json:"generated_at"`
}
ComplianceReport summarises a period of audit activity for compliance review: event volumes, chain integrity, and the security-relevant and administrative entries themselves.
func GenerateComplianceReport ¶ added in v0.3.0
func GenerateComplianceReport(log *Log, since, until time.Time) (*ComplianceReport, error)
GenerateComplianceReport builds a ComplianceReport over entries with timestamps in [since, until]. Zero bounds are open-ended. ChainValid reflects Verify over the whole live log, not just the reported window — a tampered entry outside the window still invalidates the log.
func (*ComplianceReport) WriteCSV ¶ added in v0.3.0
func (r *ComplianceReport) WriteCSV(w io.Writer) error
WriteCSV renders the report as metric rows (section,key,value) for spreadsheet analysis.
func (*ComplianceReport) WriteJSON ¶ added in v0.3.0
func (r *ComplianceReport) WriteJSON(w io.Writer) error
WriteJSON renders the report as indented JSON for SIEM ingestion.
func (*ComplianceReport) WriteMarkdown ¶ added in v0.3.0
func (r *ComplianceReport) WriteMarkdown(w io.Writer) error
WriteMarkdown renders the report as a human-readable Markdown document.
type Entry ¶
type Entry struct {
Seq uint64 `json:"seq"`
Timestamp time.Time `json:"timestamp"`
Actor string `json:"actor"` // user ID, "system", "cli", or an IP
Action string `json:"action"` // e.g. "config.reload", "secret.set"
Resource string `json:"resource"` // what was acted on
Detail map[string]any `json:"detail,omitempty"`
Hash string `json:"hash"`
}
Entry is a single audit record. Hash is the HMAC chaining this entry to the previous one; it is computed over the previous hash plus this entry's fields.
type Log ¶
type Log struct {
// contains filtered or unexported fields
}
Log is an append-only audit log backed by a newline-delimited JSON file. It is safe for concurrent Append calls.
func NewLog ¶
NewLog opens (creating if needed) the audit log at path and reads the tail so new entries continue the existing chain. hmacKey keys the HMAC-SHA256 chain.
func (*Log) Append ¶
func (l *Log) Append(_ context.Context, actor, action, resource string, detail map[string]any) error
Append writes a new entry to the log with the next sequence number and a hash chaining it to the previous entry. It is safe for concurrent use.
func (*Log) Archive ¶ added in v0.3.0
Archive rotates the live log into audit-<year>-<month>.log.gz beside it and starts a fresh log (the hash chain restarts at seq 1, so Verify stays valid for both the archive's snapshot and the new live log). Archives older than ArchiveRetention are pruned. It returns the archive path, or "" when the live log is empty.
func (*Log) ArchiveIfOver ¶ added in v0.3.0
ArchiveIfOver rotates the live log only when it exceeds limit bytes (<= 0 uses ArchiveThreshold), returning the archive path and whether it rotated.
func (*Log) Query ¶
func (l *Log) Query(filter QueryFilter) ([]Entry, error)
Query returns the entries matching filter. Without a Limit results are in chronological (oldest-first) order; with a Limit the newest matches are returned first, capped at Limit.
func (*Log) Rekey ¶ added in v0.3.0
Rekey rewrites the entire live log, recomputing the HMAC chain under newKey, used by the master-key migration (production audit C1) to move a legacy cluster-name-keyed log onto the master-derived key. The sequence numbers, timestamps, and payloads are preserved; only the chain hashes are recomputed. The pre-migration log verifies under the OLD key (this Log's current key); after Rekey it verifies under newKey. It returns an error if the existing chain does not verify under the current key (refusing to "launder" a tampered log onto a fresh key).
type QueryFilter ¶
type QueryFilter struct {
Actor string
Action string
Resource string
Since time.Time
Until time.Time
Limit int
}
QueryFilter restricts which entries Query returns. Zero-valued fields are not applied. Since and Until bound the timestamp (inclusive). Limit caps the result count and, when set, returns the newest matching entries first.