docs(security): re-verify the nine-hour window, and decide Zeek's half elsewhere (#441) - #489
Merged
Merged
Conversation
…f elsewhere (#441) #441 asked for two absence rules. SuricataLogsStopped landed on 2026-09-12 in PR #459 and is live — the ruler reports it health=ok, state=inactive. This records what the second half turned out to be, and re-reads the stream the first half was sized against. RE-VERIFIED, AND IT HOLDS. Measured again on 2026-09-17 over the full current retention (27.7 days to 22:25 UTC, five-minute buckets, same method as the original): the worst aggregate silence is 80 minutes against 75 five weeks ago, six gaps exceeded an hour, none exceeded two. Nine hours keeps nearly seven times the headroom DhcpLeaseLogsStopped settled on. The aggregate design earned its keep in the interval. igc0.10 alone crossed nine hours SEVEN times, worst 47.5 hours, so the per-interface rule the issue started from would have paged seven times in a fortnight. The rule's comment now carries both readings. One number is not comparable and the comment says so rather than presenting a single series: 135 gaps over thirty minutes here against 54 on 2026-09-12. That is bucket alignment and which streams were summed, not a change in Suricata — the long tail, which is the half that sets the window, agrees. Noted too that `interface` is only stamped from 2026-09-02, so the per-interface figures cover 13.7 days against the aggregate's 27.7. ZEEK'S HALF IS NOT A LOKI RULE, AND BELONGS TO #437. The issue proposed ZeekLogsStopped as the same shape against the lab's Loki once #437 existed. #437 existing is not sufficient, and would not make it right: - #437 puts Zeek's logs on alexander and never on 10.0.99.20, which ADR-0007 requires and ADR-0039 reaffirms by keeping the mirror on Saruman's own bridge. - ADR-0020 gives that stack no Alertmanager on purpose. stacks/lab/loki/ therefore ships no ruler and no rules/, and its config says why: a ruler with nowhere to deliver evaluates rules and discards the result, which reads as coverage and is not. - ADR-0028 revisited that exact boundary, let guest liveness cross and kept guest telemetry in the lab, and named what stays uncovered. #437 already carries the right instrument — a homelab_zeek_mirror_active textfile gauge read on the hypervisor, crossing as guest state under ADR-0028. Zeek's liveness is a metric question answered where Zeek is built, so #441 ends here rather than holding a slot behind a Wave 2 dependency that itself waits on #414. docs/security.md states that limit next to the three it already states; the roadmap records the whole of #441 in one entry, since it had none. What this proves and what it does not, unchanged: Loki rules still have no unit-test harness, so check_loki_rules.sh shows the rule parses and the ruler evaluates it, not that it fires. No rule is added or altered here — the counts stay at 82 + 18 and this is comment and prose only. Verified: ./scripts/validate.sh (3 skipped, not the deployment checkout), make check-loki-rules (18 rules + 30 dashboard expressions, 48 evaluated), python3 scripts/check_docs.py (82 + 18, 10 assertions), ./scripts/lint.sh --require-all. Refs #441 Refs #437 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What changed
Records the outcome of #441 rather than implementing it: its Suricata half
landed five days ago in #459 and is live, and its Zeek half turns out to belong
to #437 as a metric, not here as a Loki rule. Comment and prose only — no alert
rule is added or altered, and the counts stay at 82 Prometheus + 18 Loki.
Three files:
loki/rules/security.rules.yaml— theidsblock comment gains the2026-09-17 re-measurement beside the 2026-09-12 one it was sized from.
docs/security.md— the Suricata passage records the re-verification, and anew paragraph states the limit none of the three above it names: Suricata is
not a protocol logger, that ground is Zeek's, and Zeek's absence is not
answerable from this Loki.
docs/roadmap.md— aDoneentry for Alert on a sensor that stops logging: absence rules for Suricata and Zeek #441, which had none. Neither Alert on a sensor that stops logging: absence rules for Suricata and Zeek #441 norRun Zeek on a mirror port, and see the VLAN 30 traffic the firewall never will #437 appeared anywhere in the roadmap.
Why
The window still holds, re-read rather than assumed. Measured again over the
full current retention — 27.7 days to 2026-09-17 22:25 UTC, five-minute buckets:
igc0.20(Skids)igc0.10(Degens)The worst aggregate silence grew from 75 to 80 minutes in five weeks, so nine
hours keeps nearly seven times the headroom
DhcpLeaseLogsStoppedsettled on.The aggregate design earned its keep:
igc0.10alone crossed nine hours seventimes, so the per-interface rule #441 opened with would have paged seven times
in a fortnight.
One number is deliberately not compared, and the comment says so: 135 gaps over
thirty minutes here against 54 on 2026-09-12. That is bucket alignment and which
streams were summed, not a change in Suricata; the long tail, which is the half
that sets the window, agrees.
interfaceis also only stamped from 2026-09-02,so the per-interface rows cover 13.7 days against the aggregate's 27.7.
Zeek's half is not a Loki rule. #441 proposed
ZeekLogsStoppedagainst thelab's Loki once #437 existed. #437 existing is not sufficient:
alexanderand never on10.0.99.20— ADR-0007requires it, ADR-0039 reaffirms it by keeping the mirror on
Saruman's bridge.stacks/lab/loki/shipsno ruler and no
rules/, and its config says why: a ruler with nowhere todeliver evaluates rules and discards the result, which reads as coverage and
is not.
telemetry in the lab, and named what stays uncovered.
#437 already carries the right instrument — a
homelab_zeek_mirror_activetextfile gauge read on the hypervisor, crossing as guest state under ADR-0028.
So Zeek's liveness is answered where Zeek is built, and #441 is being closed
separately rather than held behind a Wave 2 dependency that itself waits on #414.
Blast radius
None. Documentation and one YAML comment; no rule, no query, no port, no
credential. The rules file is a directory bind mount, so the comment reaches the
container on the next converge — and converge is report-only, so merging deploys
nothing.
secrets/*.sops.yamlVerification
make validatepassesThe live ruler, before and after — the rule is untouched and in its good state:
docs/security.md,docs/roadmap.md)What this does not prove. Loki rules still have no unit-test harness, so
check_loki_rules.shshows the rule parses and the ruler evaluates it — notthat it fires.
🤖 Generated with Claude Code