Skip to content

Add Linux auditd log parser - #36

Merged
copyleftdev merged 1 commit into
mainfrom
feat/auditd
May 31, 2026
Merged

copyleftdev merged 1 commit into
mainfrom
feat/auditd

Conversation

@copyleftdev

@copyleftdev copyleftdev commented May 31, 2026 •

Copy link
Copy Markdown
Owner

Implements the auditd plugin — issue #12.

What

/var/log/audit/audit.log lines are
type=<TYPE> msg=audit(<epoch>:<serial>): key=value ... (optionally node=<host>
prefixed). AuditdParser pulls the distinctive audit message ID out of
msg=audit(...) — epoch as a Float (for coll.cusum / cadence on bursty
activity) and serial as the event id — then parses the remaining key=value
fields. type and syscall are the categorical columns dist reads as
exec/syscall mix drift.

Field values are bare (type-inferred: syscall=2→Int, exit=-13→Int),
double-quoted (comm="cat"), or single-quoted (auditd USER_* records carry a
msg='...' payload with spaces) — quoted values kept verbatim as Str. The
audit ID is split out with split_once (no index arithmetic), so the record
split has no off-by-one mutation surface.

Routing

  • Detected by the unmistakable msg=audit( signature (STRONG, beats logfmt's
    TEXT).
  • Claims no extension (audit.log is too generic to hijack).

Errors

A line without a valid msg=audit(...) (missing marker, no : separator,
non-numeric serial) is a clean AxError::Parse.

Gates

  • fmt / clippy -D warnings / full workspace tests green (both feature sets).
  • Mutation gate: 0 surviving mutants on auditd.rs (4 loop-bound timeouts in
    the field scanner). The extensions() → empty-slice mutant is a documented
    equivalent
    (same as Zeek/Journal/Eve/CloudTrail).
  • Smoke: an audit.log slice routes as auditd with epoch/serial/syscall
    typed.

Closes #12

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added support for parsing Linux auditd logs with automatic record detection and key=value field extraction into tabular format.

New AuditdParser in ax-normalize for /var/log/audit/audit.log. Each line is
type=<TYPE> msg=audit(<epoch>:<serial>): key=value ... (optionally node=<host>
prefixed). We pull the distinctive audit message ID out of msg=audit(...) —
epoch as a Float (for coll.cusum / cadence on bursty activity) and serial as the
event id — then parse the remaining key=value fields. type and syscall are the
categorical columns dist reads as exec/syscall mix drift.

Field values are bare (type-inferred, syscall=2 -> Int, exit=-13 -> Int),
double-quoted (comm="cat"), or single-quoted (auditd USER_* records carry a
msg='...' payload with spaces) — quoted values kept verbatim as Str. The audit
ID is split out with split_once (no index arithmetic), so the record splitting
has no off-by-one mutation surface.

Detected by the unmistakable msg=audit( signature (STRONG, beats logfmt's TEXT);
claims no extension (audit.log is too generic). A line without a valid
msg=audit(...) is a clean Parse error.

Mutation gate: 0 surviving mutants on the new file. The extensions() ->
empty-slice mutant is a documented equivalent (same as Zeek/Journal/Eve/CloudTrail).

Closes #12

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented May 31, 2026 •

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 89f2173f-cb62-410e-9ede-0c5ac2b4b377

📥 Commits

Reviewing files that changed from the base of the PR and between db69ad5 and 72bb598.

📒 Files selected for processing (4)
  • .cargo/mutants.toml
  • crates/ax-normalize/src/parser.rs
  • crates/ax-normalize/src/parsers/auditd.rs
  • crates/ax-normalize/src/parsers/mod.rs

📝 Walkthrough

Walkthrough

This PR adds a complete Linux auditd log parser to the anomalyx ax-normalize module. The implementation detects auditd records via msg=audit(epoch:serial) markers, extracts metadata timestamps, and parses trailing key=value fields with type inference, quoted string support, and space-preserving single-quoted values. The parser is registered into the default format registry and verified through test expectations and mutation testing exclusions.

Changes

auditd Log Parser Addition

Layer / File(s) Summary
AuditdParser implementation and unit tests
crates/ax-normalize/src/parsers/auditd.rs
Implements AuditdParser struct with FormatParser trait, including parse_fields tokenizer for bare/quoted/single-quoted key=value pairs with type inference, parse_record for epoch/serial extraction from msg=audit(...) markers, sniffing by msg=audit( presence, and comprehensive unit tests validating field parsing, quoting behavior, spaces in quoted values, node prefix handling, error cases, and parser registry resolution.
Parser module wiring and registry registration
crates/ax-normalize/src/parsers/mod.rs
Adds pub mod auditd; module declaration and pub use auditd::AuditdParser; re-export, then registers AuditdParser in default_registry() at the deterministic ordering position before syslog parsers.
Registry test expectations update
crates/ax-normalize/src/parser.rs
Updates default_registry_lists_all_formats test assertions in both polars-enabled and non-polars test branches to include "auditd" in the expected ordered format list.
Mutation testing exclusion
.cargo/mutants.toml
Adds mutation exclusion for AuditdParser>::extensions.*Vec::new, documented as behaviorally equivalent since the parser declares no file extensions.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

  • copyleftdev/anomalyx#26: Both PRs modify crates/ax-normalize/src/parser.rs's default_registry_lists_all_formats expectations and register a new built-in parser in the default registry.
  • copyleftdev/anomalyx#32: Both PRs extend the ParserRegistry deterministic ordering by adding a new built-in parser module with corresponding test expectation updates.

Poem

🐰 Hops through logs with auditd grace,
Epoch, serial find their place,
Key=value fields now neatly parse,
No extensions—yet bold and sparse!
Registry joins the builder's race. 🎉

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/auditd

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@copyleftdev
copyleftdev merged commit f358611 into main May 31, 2026
1 of 2 checks passed
@copyleftdev
copyleftdev deleted the feat/auditd branch May 31, 2026 06:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add an auditd log parser

1 participant