add rule generalization, sized LLM defaults, ops docs, and UI polish
Feedback rules can now be suggested for merging when a human has already reviewed the same pattern multiple times (never guesses about new values). LLM defaults sized for constrained VRAM instead of llama3.3/llama3.1. Adds systemd units, a state backup script, and reverse-proxy auth guidance for production deployment. Findings view is collapsible and sorts suggested-review rows to the top for a quicker overview.
This commit is contained in:
90
README.md
90
README.md
@@ -186,7 +186,8 @@ stored under `graylog_stream_profiles` in `state/fgai-config.json`.
|
||||
The Settings page also shows recommended stream profiles built from observed
|
||||
field coverage and cardinality. These recommendations use deterministic
|
||||
discovery first, then can optionally be refined by a local Ollama profile advisor
|
||||
model such as `qwen3:8b` or `qwen3:14b`. Enable `Ollama profile advisor` and set
|
||||
model such as `qwen2.5:3b-instruct` (default) or a larger model on more capable
|
||||
hardware. Enable `Ollama profile advisor` and set
|
||||
`Profile advisor model` in Settings. Advisor output must be valid JSON and is
|
||||
validated against fields actually seen in the stream before it can be applied.
|
||||
Unknown fields, raw message fields, internal `fgai_*` fields, and unknown
|
||||
@@ -671,16 +672,28 @@ fgai suggest-blocks --logs logs/fg_syslog.jsonl --execute --expiry-minutes 60
|
||||
Optional local LLM summary through Ollama:
|
||||
|
||||
```bash
|
||||
ollama pull llama3.3
|
||||
ollama pull qwen2.5:7b-instruct
|
||||
fgai analyze-logs --logs logs/fg_syslog.jsonl --llm --llm-timeout 300
|
||||
```
|
||||
|
||||
For slower machines or large models:
|
||||
For slower machines, pick a smaller model instead of raising the timeout:
|
||||
|
||||
```bash
|
||||
OLLAMA_MODEL=llama3.1 OLLAMA_TIMEOUT=300 fgai analyze-logs --logs logs/fg_syslog.jsonl --llm
|
||||
OLLAMA_MODEL=qwen2.5:3b-instruct OLLAMA_TIMEOUT=300 fgai analyze-logs --logs logs/fg_syslog.jsonl --llm
|
||||
```
|
||||
|
||||
**Sizing the model to your GPU**: the defaults (`qwen2.5:7b-instruct` for the
|
||||
dashboard assessment, `qwen2.5:3b-instruct` for the profile advisor) target a
|
||||
6-8 GB VRAM card at Q4 quantization with some headroom for context. On a
|
||||
memory-constrained card (6 GB or less, e.g. a mobile/low-power GPU), drop both
|
||||
to `qwen2.5:3b-instruct` or smaller — tight VRAM causes Ollama to spill onto
|
||||
CPU, which shows up as slow or timed-out assessments rather than an obvious
|
||||
out-of-memory error. On a workstation-class GPU with 16 GB+ VRAM, a larger
|
||||
model such as `qwen3:14b` for the dashboard assessment will give noticeably
|
||||
better analysis quality. The profile advisor only ever classifies a handful
|
||||
of ambiguous fields per call (see the Graylog MCP section below), so it stays
|
||||
small and fast even on constrained hardware without much quality loss.
|
||||
|
||||
## Optional FortiGate Input
|
||||
|
||||
## Synthetic Windows Test Input
|
||||
@@ -723,7 +736,7 @@ end
|
||||
- `FORTIGATE_VERIFY_TLS`: `true` or `false`, defaults to `true`.
|
||||
- `FGAI_ALLOWLIST`: comma-separated IPs/CIDRs never to block.
|
||||
- `OLLAMA_HOST`: defaults to `http://127.0.0.1:11434`.
|
||||
- `OLLAMA_MODEL`: defaults to `llama3.1`.
|
||||
- `OLLAMA_MODEL`: defaults to `qwen2.5:7b-instruct`. Size this to your GPU's VRAM — see the sizing note above.
|
||||
- `OLLAMA_TIMEOUT`: Ollama request timeout in seconds, defaults to `180`.
|
||||
- `FGAI_LLM`: set to `1` to enable dashboard Ollama analyst notes.
|
||||
- `FGAI_LLM_INTERVAL`: seconds between dashboard LLM notes, defaults to `300`.
|
||||
@@ -743,3 +756,70 @@ The agent separates detection from enforcement:
|
||||
- Source IPs must be globally routable and outside the allowlist.
|
||||
- Blocking requires `--execute`.
|
||||
- The FortiGate API call is limited to the quarantine/banned user monitor endpoint.
|
||||
|
||||
## Production Deployment
|
||||
|
||||
`start.sh` is convenient for a single machine you're logged into, but has no
|
||||
supervision (a crashed process just stays dead) and no boot-time start.
|
||||
|
||||
### Running under systemd
|
||||
|
||||
Unit files for the monitor, dashboard, and optional local syslog listener are
|
||||
in `systemd/`, with full setup and update instructions in
|
||||
[`systemd/README.md`](systemd/README.md). They mirror `start.sh`'s exact
|
||||
process arguments, add `Restart=on-failure`, and run under a dedicated
|
||||
`signalscope` system user with `ProtectSystem=strict`/`ProtectHome=true`
|
||||
sandboxing rather than as root.
|
||||
|
||||
### Backup and Restore
|
||||
|
||||
Everything SignalScope needs to restore — runtime configuration, feedback
|
||||
rules, behavior baselines, incident state, and caches — lives under `state/`.
|
||||
Nothing else needs backing up; logs and exports are reproducible/disposable.
|
||||
|
||||
```bash
|
||||
scripts/backup_state.sh # writes to ./backups/signalscope-state-<timestamp>.tar.gz
|
||||
scripts/backup_state.sh /path/to/backups # or a custom destination
|
||||
```
|
||||
|
||||
SQLite databases (`fgai-baseline.sqlite3`, `signalscope-history.sqlite3`,
|
||||
`signalscope-status-cache.sqlite3`) are backed up with `sqlite3 .backup`,
|
||||
which takes a consistent snapshot even while the monitor is actively writing
|
||||
to them, rather than a plain file copy that can capture a torn/inconsistent
|
||||
write mid-transaction. JSON files (`fgai-config.json`,
|
||||
`signalscope-feedback.json`, `signalscope-incidents.json`,
|
||||
`threat-intel-cache.json`) are already written atomically by SignalScope
|
||||
(temp file + rename) and are copied directly.
|
||||
|
||||
To restore: stop the monitor and dashboard, extract the archive's contents
|
||||
over `state/`, then restart.
|
||||
|
||||
### Exposing the Dashboard Beyond Loopback
|
||||
|
||||
The dashboard has **no built-in authentication** — its entire access-control
|
||||
model is "only accept connections from `127.0.0.1`" (`start.sh`'s and the
|
||||
systemd unit's default `--host 127.0.0.1`). API routes that change state
|
||||
(`POST /api/config`, `/api/feedback`, `/api/feedback/bulk`, incident actions,
|
||||
and more) additionally check that the client's socket address is loopback,
|
||||
regardless of what `Host` header a request carries.
|
||||
|
||||
If you need to reach the dashboard from another machine, do not change
|
||||
`--host` to `0.0.0.0` directly — put an authenticating reverse proxy in front
|
||||
of it instead and keep SignalScope itself bound to loopback. For example,
|
||||
with Caddy:
|
||||
|
||||
```
|
||||
signalscope.internal.example.com {
|
||||
basicauth {
|
||||
analyst $2a$14$... # generate with: caddy hash-password
|
||||
}
|
||||
reverse_proxy 127.0.0.1:8088
|
||||
}
|
||||
```
|
||||
|
||||
Or nginx with `auth_basic` / an `auth_request` subrequest to whatever SSO the
|
||||
rest of your infrastructure already uses. Either way, terminate TLS at the
|
||||
proxy and keep the token/credential prompts outside SignalScope's own process
|
||||
— since state-changing routes only trust the *proxy's* loopback connection,
|
||||
not the original client, the proxy is the only thing standing between a
|
||||
public request and dashboard write access once `--host` is opened up.
|
||||
|
||||
Reference in New Issue
Block a user