enodia-sentinal/docs/COMMAND_REFERENCE.md
Luna a56d72edd6 Add incident grouping (roadmap v0.8: incident list/show/export)
Collapse related alerts into one incident, process-lineage first with a
time-window fallback. Each alert batch's flagged PIDs are walked up the
/proc PPid chain into a lineage set (excluding pid 0/1 so everything
doesn't correlate through init); batches whose lineage sets intersect —
sharing a process or a common ancestor like the web server or SSH
session — join the same incident. PID-less batches (FIM drift, package
tamper, hidden modules) fall back to the most recently active open
incident within incident_window.

snapshot.capture now computes lineage and records each snapshot into a
JSON incident index (incidents.json), writing incident_id into both the
report JSON (report level, so the per-alert schema is untouched) and the
text header. New commands:

  incident list              incidents newest-first, with signatures
  incident show <id>         summary + time-ordered snapshot timeline
  incident export <id>       JSON bundle: record + inlined snapshots

The lineage/assign cores are pure functions; record() serializes the
index under a lock (capture runs from sweep + eBPF threads) and is
best-effort so an index problem never loses a snapshot. 17 new tests
(lineage, assign, record, and an end-to-end capture→group→CLI path).
Config: incident_tracking / incident_window / incident_lineage_depth.
Docs + sample config updated; closes the last v0.8 roadmap item.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-10 17:52:42 -07:00

291 lines
7.6 KiB
Markdown

# Enodia Sentinel Command Reference
This is the operator-facing command contract for the current local agent. Commands
are intentionally plain: they either inspect state, manage baselines, run the
daemon, or expose existing evidence.
Global options:
```bash
enodia-sentinel --version
enodia-sentinel -c /path/to/config.toml <command>
```
If no command is provided, `run` is used.
## Service Commands
### `run`
```bash
enodia-sentinel run
```
Starts the daemon loop. This is the command used by the systemd service. It
builds or loads baselines, starts optional event monitoring, writes heartbeats,
runs detector sweeps, captures snapshots, and sends notifications.
Expected use: systemd, not an interactive shell.
### `check`
```bash
enodia-sentinel check
```
Runs the enabled detector set once and prints alerts. This forces the SUID scan
and arms baseline-gated detectors immediately, so it is useful for health checks
and debugging.
Exit code:
- `0`: no alerts.
- `0`: alerts may still print today; this command is currently human-oriented,
not a strict CI gate.
### `baseline`
```bash
enodia-sentinel baseline
```
Rebuilds listener and SUID baselines under `log_dir`. Use after installing on a
known-good host or after intentionally adding persistent services or privileged
helpers.
Do not run this to silence unexplained findings.
## Detection and Integrity Commands
### `list-detectors`
```bash
enodia-sentinel list-detectors
```
Prints the poll detectors and whether each is enabled by config.
### `rootcheck`
```bash
enodia-sentinel rootcheck
```
Runs anti-rootkit cross-view checks once:
- PIDs alive via `kill(pid, 0)` but missing from `/proc`.
- Live modules in `/sys/module` but missing from `/proc/modules`.
- Listening TCP ports in `/proc/net/tcp*` but missing from `ss`.
- Network interfaces in promiscuous mode.
Exit code:
- `0`: no rootcheck findings.
- `1`: one or more rootcheck alerts.
### `fim-baseline`
```bash
enodia-sentinel fim-baseline
```
Builds the SHA-256 file integrity baseline for configured critical paths plus
Sentinel's own footprint.
Use on a known-good host. The package hook also calls `fim-update` after normal
package transactions.
### `fim-update`
```bash
enodia-sentinel fim-update
```
Refreshes the FIM baseline. This exists primarily for the package manager hook.
Manual use should be treated as an acknowledgement that the current file state
is legitimate.
### `fim-check`
```bash
enodia-sentinel fim-check
enodia-sentinel fim-check --packages
```
Diffs current file state against the FIM baseline. With `--packages`, also runs
package-owned file verification through the package manager (`pacman -Qkk` on
Arch).
Exit code:
- `0`: no baseline changes.
- `1`: one or more added, removed, or modified files.
### `pkgdb-check`
```bash
enodia-sentinel pkgdb-check
```
Checks whether the local package database fingerprint changed outside a logged
package transaction. This catches an attacker rewriting stored package checksums
to hide a modified binary.
Exit code:
- `0`: package DB matches the anchor or was legitimately re-anchored.
- `1`: out-of-band DB tampering suspected.
### `pkgdb-verify`
```bash
enodia-sentinel pkgdb-verify
enodia-sentinel pkgdb-verify --sample 200
```
Compares on-disk package-owned files to SHA-256 hashes from `.MTREE` manifests
inside cached signed packages. This is independent of the mutable local package
database.
The command also flags insecure global `SigLevel` settings and warns if the
pacman keyring is missing.
Exit code:
- `0`: sampled files match and signature policy is not downgraded.
- `1`: a signed-package mismatch or insecure signature setting was found.
### `incident`
```bash
enodia-sentinel incident list [--json]
enodia-sentinel incident show <incident-id> [--json]
enodia-sentinel incident export <incident-id>
```
Groups related alerts into incidents so one intrusion reads as one story instead
of several disconnected alerts. Grouping is **process-lineage first** (alerts
sharing a PID or a common ancestor — the web server or SSH session they descend
from), with a **time-window fallback** for alerts that carry no live PID (FIM
drift, package tamper, hidden modules). Each captured snapshot records an
`incident_id`; the index lives in `incidents.json` under `log_dir`.
- `list` — incidents newest-first: id, last seen, severity, alert count, and the
signatures involved.
- `show <id>` — incident summary plus a time-ordered timeline of its member
snapshots (time, severity, signatures, PIDs, and the snapshot file to open).
- `export <id>` — a single JSON bundle of the incident record with every member
snapshot report inlined, suitable for handoff or offline analysis.
Tuning lives in config: `incident_window` (how long an incident stays open for
new alerts) and `incident_lineage_depth` (ancestors walked when correlating).
Exit code: `0` on success; `1` if the incident id is unknown; `2` if `show`/
`export` is called without an id.
### `posture check`
```bash
enodia-sentinel posture check
enodia-sentinel posture check --json
```
Audits host configuration hygiene — the conditions that make a host *easy* to
attack, as opposed to an attack in progress:
- SSH: root login, password authentication, and empty-password logins.
- sudo: passwordless (`NOPASSWD`) rules, disabled authentication, and
group/world-writable sudoers files.
- World-writable or non-root-owned `PATH` directories (binary-hijack vectors).
- Loose permissions on sensitive files (`/etc/shadow`, `/etc/passwd`, ...).
- Downgraded package-signature policy (`SigLevel`).
Findings are advisory and reuse the standard alert JSON shape (`--json`). This
command does not run inside the daemon and never blocks startup.
Exit code:
- `0`: no posture findings.
- `1`: one or more findings.
## Evidence and Operator Commands
### `status`
```bash
enodia-sentinel status
enodia-sentinel status --json
```
Prints a local health and alert summary: daemon running state, heartbeat age and
staleness, total alerts with per-severity counts, last alert time, and eBPF
monitor state. `--json` emits the same data as the dashboard `/api/status`
endpoint, for cron/monitoring.
Exit code:
- `0`: daemon is running and the heartbeat is fresh.
- `1`: daemon is down or the heartbeat is stale.
### `web`
```bash
enodia-sentinel web
```
Starts the read-only dashboard. By default it binds to the Tailscale interface
when available and uses bearer-token authentication for non-loopback binds.
Expected use: `enodia-sentinel-web.service`.
### `triage`
```bash
enodia-sentinel triage
```
Reads captured alert JSON snapshots and classifies distinct findings as likely
false positive or review-needed. It suggests config snippets for known benign
noise but never edits config automatically.
### `watchdog`
```bash
enodia-sentinel watchdog --url http://100.x.y.z:8787 --token <token> --max-age 120
```
Polls a remote dashboard and alerts if the sensor is down, unreachable, or has a
stale heartbeat. Run this from a separate host. A watchdog on the same machine
does not prove the protected host is alive.
Exit code:
- `0`: remote sensor is reachable and fresh.
- `1`: remote sensor is stale, down, or unreachable.
## Development Shortcuts
The Makefile wraps common local tasks:
```bash
make test
make check
make baseline
make web
make drill
```
`make install` installs a plain package directory plus a launcher wrapper. It
does not require pip or a virtualenv.
## Future Command Contracts
The roadmap reserves these command shapes:
```bash
enodia-sentinel respond plan <incident-id>
enodia-sentinel respond apply <plan-id>
```
These should be introduced with stable JSON schemas and tests before they are
documented as supported.