agent

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: 31 Imported by: 0

Documentation

Overview

Package agent is the daemon loop: tail → parse → evaluate → decide → enforce, pending verdicts ticked, everything the other packages provide wired into one running defence.

A live tail joins the present: a starting agent reads from the end of each file, stamps each line with the moment it read it — the same instant — and never resumes a position saved before it stopped. Reading a log's past is a deliberate act, either replay_on_start at boot or a dry run from the command line, and it judges by window *and* ban duration: a crossing counts only if the sanction it earns would still be in force.

One deliberate simplification remains: pending verdicts are not flushed on shutdown. Firing them early could ban what exculpatory evidence would have cleared, so a restart re-detects from fresh evidence instead.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Run

func Run(ctx context.Context, opts Options) error

Run starts the agent and blocks until the context ends. It returns the first fatal error; per-line and per-decision problems are logged and survived.

Types

type Handler

type Handler struct {
	// contains filtered or unexported fields
}

Handler writes the agent's log. It is a slog.Handler so that every package can keep logging the way it does.

func NewHandler

func NewHandler(w io.Writer, level slog.Level) *Handler

NewHandler writes to w at level and above.

func (*Handler) Enabled

func (h *Handler) Enabled(_ context.Context, l slog.Level) bool

func (*Handler) Handle

func (h *Handler) Handle(_ context.Context, r slog.Record) error

func (*Handler) WithAttrs

func (h *Handler) WithAttrs(attrs []slog.Attr) slog.Handler

func (*Handler) WithGroup

func (h *Handler) WithGroup(string) slog.Handler

type Options

type Options struct {
	ConfigDir    string
	StatePath    string        // the SQLite state file; required, Run refuses an empty one
	Applier      nft.Applier   // nil = the real nft binary
	PollInterval time.Duration // default 200ms
	RescanEvery  time.Duration // how often log_input patterns are re-read; default rescanEvery
	Logger       *slog.Logger  // nil = slog.Default()
	// Output is what Logger writes to, when the caller built it over
	// one. The agent adds log_file to it after reading the
	// configuration, and keeps it open across rotation. Nil is fine:
	// the log then goes wherever Logger already sends it.
	Output *Output
}

Options configure a run. ConfigDir is required; zero values elsewhere take defaults.

type Output

type Output struct {
	// contains filtered or unexported fields
}

Output is where the log goes. It starts as one writer — stderr, which systemd collects — and can gain a file once the configuration has been read, which is after the logger already exists.

It also survives log rotation on its own. The file is identified by (device, inode) like every other file this program follows, so when logrotate renames it away the next check notices the path no longer names the same file and reopens it. That is why no logrotate configuration ships with this: there is nothing to tell it.

func NewOutput

func NewOutput(base io.Writer) *Output

NewOutput starts writing to base alone.

func (*Output) AddFile

func (o *Output) AddFile(path string) error

AddFile starts also writing to path, creating it if it is not there. An error is returned rather than logged — the caller is the only one who can say it in the log that still works.

func (*Output) CheckRotation

func (o *Output) CheckRotation() error

CheckRotation reopens the file if the path no longer names the one that is open — which is what logrotate leaves behind when it renames or removes it. Called on the agent's own slow cadence; a stat is cheap and a log written into a deleted inode is invisible.

func (*Output) Close

func (o *Output) Close() error

Close releases the file. The base writer is the caller's.

func (*Output) Path

func (o *Output) Path() string

Path is the file being written, empty when there is none.

func (*Output) Settle

func (o *Output) Settle()

Settle releases the held start-of-run lines when no file is coming. The caller says so once it has read the configuration.

func (*Output) Write

func (o *Output) Write(p []byte) (int, error)

Jump to

Keyboard shortcuts

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