Add event rule inspection commands
This commit is contained in:
parent
1f05923e0f
commit
5db88d285e
7 changed files with 417 additions and 5 deletions
|
|
@ -61,6 +61,14 @@ def main(argv: list[str] | None = None) -> int:
|
|||
sub.add_parser("check", help="run detectors once and print alerts")
|
||||
sub.add_parser("baseline", help="rebuild listener/SUID baselines")
|
||||
sub.add_parser("list-detectors", help="list available detectors")
|
||||
rules = sub.add_parser("rules",
|
||||
help="list/show/test built-in and configured rules")
|
||||
rules.add_argument("action", nargs="?", default="list",
|
||||
choices=["list", "show", "test"],
|
||||
help="rule action (default: list)")
|
||||
rules.add_argument("target", nargs="?",
|
||||
help="sid for show, event JSON path for test, or '-'")
|
||||
rules.add_argument("--json", action="store_true", help="emit JSON")
|
||||
sub.add_parser("web", help="serve the read-only dashboard")
|
||||
sub.add_parser("triage", help="classify captured alerts as likely-FP vs review")
|
||||
sub.add_parser("fim-baseline", help="build the file-integrity baseline")
|
||||
|
|
@ -112,6 +120,8 @@ def main(argv: list[str] | None = None) -> int:
|
|||
mark = "on " if cfg.enabled(det.name) else "off"
|
||||
print(f" [{mark}] {det.name}")
|
||||
return 0
|
||||
if args.cmd == "rules":
|
||||
return _cmd_rules(cfg, args.action, args.target, args.json)
|
||||
if args.cmd == "baseline":
|
||||
return _cmd_baseline(cfg)
|
||||
if args.cmd == "check":
|
||||
|
|
@ -154,6 +164,74 @@ def main(argv: list[str] | None = None) -> int:
|
|||
return _cmd_run(cfg)
|
||||
|
||||
|
||||
def _cmd_rules(cfg: Config, action: str, target: str | None,
|
||||
as_json: bool) -> int:
|
||||
import json
|
||||
|
||||
from . import ruleops
|
||||
|
||||
if action == "list":
|
||||
rules = ruleops.list_rules(cfg)
|
||||
if as_json:
|
||||
print(json.dumps(rules, indent=2))
|
||||
return 0
|
||||
print(f"{'SID':<7} {'EVENT':<8} {'ORIGIN':<10} {'SEV':<9} "
|
||||
f"{'CLASSTYPE':<24} MESSAGE")
|
||||
for r in rules:
|
||||
print(f"{r['sid']:<7} {r['event']:<8} {r['origin']:<10} "
|
||||
f"{r['severity']:<9} {r['classtype']:<24} {r['msg']}")
|
||||
return 0
|
||||
|
||||
if action == "show":
|
||||
if not target:
|
||||
print("error: 'rules show' needs a sid", file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
sid = int(target)
|
||||
except ValueError:
|
||||
print(f"error: invalid sid: {target}", file=sys.stderr)
|
||||
return 2
|
||||
rule = ruleops.find_rule(cfg, sid)
|
||||
if rule is None:
|
||||
print(f"error: no such rule sid: {sid}", file=sys.stderr)
|
||||
return 1
|
||||
if as_json:
|
||||
print(json.dumps(rule, indent=2))
|
||||
return 0
|
||||
print(f"Rule {rule['sid']} [{rule['severity']}] {rule['signature']}")
|
||||
print(f" event: {rule['event']}")
|
||||
print(f" origin: {rule['origin']}")
|
||||
print(f" classtype: {rule['classtype']}")
|
||||
print(f" message: {rule['msg']}")
|
||||
print(" conditions:")
|
||||
for key, value in rule["conditions"].items():
|
||||
print(f" {key}: {value}")
|
||||
return 0
|
||||
|
||||
if action == "test":
|
||||
if not target:
|
||||
print("error: 'rules test' needs an event JSON path or '-'",
|
||||
file=sys.stderr)
|
||||
return 2
|
||||
try:
|
||||
alerts = ruleops.test_event(cfg, ruleops.load_event_json(target))
|
||||
except (OSError, ValueError, json.JSONDecodeError) as exc:
|
||||
print(f"error: cannot test event: {exc}", file=sys.stderr)
|
||||
return 2
|
||||
if as_json:
|
||||
print(json.dumps([a.to_dict() for a in alerts], indent=2))
|
||||
return 0 if alerts else 1
|
||||
if not alerts:
|
||||
print("No rules matched.")
|
||||
return 1
|
||||
for a in alerts:
|
||||
print(f"[{a.severity}] sid={a.sid} {a.signature} {a.detail}")
|
||||
return 0
|
||||
|
||||
print(f"error: unsupported rules action: {action}", file=sys.stderr)
|
||||
return 2
|
||||
|
||||
|
||||
def _cmd_watchdog(cfg: Config, url: str, token: str, max_age: int,
|
||||
verify_tls: bool = True) -> int:
|
||||
from . import notify
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue