replay

package
v0.0.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: AGPL-3.0 Imports: 11 Imported by: 0

Documentation

Overview

Package replay reads a log's past.

A live agent joins the present and stamps each line with the moment it read it, which is the same instant and costs nothing. Reading what already happened is a different act, and a deliberate one: an operator turning up after an attack began, or asking what a rule would have done before trusting it.

Two things make it different from a live run, and both matter:

  • events are dated by the line, not by the reading. journald records its own time and needs no parsing; a file needs its parser to say where its timestamp is (time_field). A file's worth of traffic replayed as if it were simultaneous would have any windowed rule ban everyone in it.
  • a crossing only becomes a sanction if that sanction **would still be in force now**. Window and ban duration, not window alone: an attack five hours old that earns six hours still earns them; the same attack earning five minutes earns nothing. This is what lets someone arrive late and still stop who is behind it, and it is the part fail2ban's scan-on-start does not do.

The evaluator is the same code as the live one — that is the point of it being a pure function of an ordered event stream (SPEC §5.3).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Options

type Options struct {
	// Since limits the replay to lines no older than this. Zero reads
	// everything the files hold.
	Since time.Duration
	// Now is what "still in force" is measured against. Zero means the
	// clock.
	Now time.Time
	// Rule, when set, replays only that rule — the shape of "what would
	// this one do", without the noise of every other.
	Rule string
	// MaxEvents caps how many hits the replay holds at once. Zero takes
	// the default. Past the cap the oldest go first — a verdict that can
	// still be in force is made of recent evidence — and every drop is
	// counted and reported (Capped), never silent.
	MaxEvents int
}

Options bound what is read and how it is judged.

type Report

type Report struct {
	Files    []string
	Lines    int
	Hits     int
	Undated  int // lines whose own time could not be read
	Oldest   time.Time
	Newest   time.Time
	Verdicts []Verdict
	InForce  int // sanctions that would still be enforced now
	Lapsed   int // crossings whose sanction has already run out
	// NoSanction counts crossings of rules with no ban outcome — alert
	// and record-only rules. They are neither in force nor lapsed:
	// counting them "too old to matter" would be a lie about rules that
	// never ban anything.
	NoSanction int
	ByRule     map[string]int
	// Capped counts the hits dropped to stay inside MaxEvents — the
	// oldest first. When it is not zero the judgment covers the newest
	// evidence only, from CappedSince onwards, and the caller says so.
	Capped      int
	CappedSince time.Time
	// Inactive lists the rules this agent cannot evaluate yet, with the
	// reason — they took no part in the judgment.
	Inactive []string
	// Where the reading ended, for the caller that will tail the same
	// sources next: the position after each file's last line, and each
	// journald unit's last cursor. A live tail seeded with these joins
	// the present with no gap — within one process's life, never across
	// a restart.
	FilePos map[string]tail.Position
	Cursors map[string]string
}

Report is what a replay found.

func Run

func Run(cfg *config.Config, opts Options) (*Report, error)

Run replays the configured log inputs and reports what the rules make of them. It reads and computes; it writes nothing, enforces nothing, and touches no store — applying the result is the caller's decision.

type Verdict

type Verdict struct {
	Trigger  eval.Trigger // the crossing itself, for a caller that will act on it
	Rule     string
	Offender string
	At       time.Time // when the evidence completed, by the lines' own clock
	Evidence []string  // the lines that convicted, as they were written
	Ends     time.Time // when the sanction it earns would run out
	InForce  bool      // whether that is still in the future
}

Verdict is one crossing and what became of it.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL