Add host posture checks (roadmap v0.8: posture check)

Add `enodia-sentinel posture check` — a config-hygiene audit that finds
the conditions making a host easy to attack, complementing the live
detectors. Checks: SSH root/password/empty-password login (Include-aware,
first-wins sshd resolution), passwordless and group/world-writable
sudoers, world-writable or non-root PATH directories, loose permissions
on sensitive files (/etc/shadow, /etc/passwd, ...), and downgraded
package-signature policy (reusing pkgdb.siglevel_alert).

Findings reuse the Alert type, so they serialize through the existing
JSON/triage pipeline (`posture check --json`). Each check is a pure
evaluator over injected content/stat facts plus a thin system reader, so
the 18 new tests need no root or live /etc. Posture is command-driven and
never runs in the daemon loop, per the v0.8 exit criterion.

SIDs 100040-100047 (classtype host-posture). Sample config and docs
(COMMAND_REFERENCE, OPERATIONS, ROADMAP, SPECIFICATION) updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-10 05:15:06 -07:00
parent 6ff2087329
commit 9ebc355936
9 changed files with 520 additions and 6 deletions

View file

@ -83,6 +83,12 @@ class Config:
rootcheck_interval: int = 300 # seconds between cross-view sweeps
rootcheck_pid_cap: int = 65536 # upper PID to brute-force via kill(0)
# host posture (config hygiene; advisory, command-driven, never blocks startup)
posture_sshd_config: str = "/etc/ssh/sshd_config"
posture_sudoers: str = "/etc/sudoers"
posture_sudoers_dir: str = "/etc/sudoers.d"
posture_path: tuple[str, ...] = () # PATH dirs to audit ('' = safe default set)
# eBPF on-ramp
capture_execve_bpftrace: bool = False
# Event-driven eBPF execve monitor (catches short-lived processes the poll