Skip to content

Session-scoped network rules with layered resolution#48

Merged
tito merged 2 commits intomainfrom
mathieu/session-network-rules
Apr 14, 2026
Merged

Session-scoped network rules with layered resolution#48
tito merged 2 commits intomainfrom
mathieu/session-network-rules

Conversation

@tito
Copy link
Copy Markdown
Contributor

@tito tito commented Apr 14, 2026

Summary

  • Greywall can now attach network rules to a session at creation time; rules are scoped to the session lifetime and auto-deleted when the session ends, expires, or is superseded.
  • Layered rule resolution: global > session > builtin > default-deny. Within a layer, specificity wins and deny beats allow at equal specificity.
  • Per-container allow_all for greywall learning mode (skips ACL for that container).
  • Built-in localhost rules (127.0.0.1, ::1, localhost) seeded at the lowest priority so loopback always works.
  • Session rules are JOINed with the sessions table at match time, and a session rule only matches when its session is the most recently created active session for the connecting container. This prevents an older session's rules from leaking into a newer session started for the same container (e.g. greywall run with `--no-network-rules`).

Test plan

  • Unit tests for session rule create/upsert/delete/expire lifecycle
  • Unit tests for layered resolution (global > session > builtin)
  • Unit test: session rule does not match after its session is deleted
  • Unit test: newer session for the same container supersedes older session rules
  • Unit tests for built-in localhost rules and per-container allow-all

tito added 2 commits April 13, 2026 18:04
Add the ability for greywall to send network rules as part of session
creation. Rules are scoped to the session lifetime and auto-deleted
when the session ends or expires.

Key changes:
- Migration 12: session_id column on rules, allow_all on sessions,
  built-in localhost rules (127.0.0.1, ::1, localhost)
- SessionCreateInput gains NetworkRules and AllowAll fields
- Layered rule resolution: global > session > builtin > default-deny
- Per-container allow_all for learning mode (skips ACL for that container)
- Heartbeat extends session rule expiry alongside session TTL
- UI shows source badges (session/builtin) on rules list
- Comprehensive tests for the full lifecycle
Session rules were leaking into newer sessions for the same container.
If session 1 was still alive (not expired/deleted) and session 2 was
created for the same container with no network rules, session 1's rules
kept matching session 2's traffic. The JOIN we added earlier only
verified the rule's session was still alive -- not that it was the
container's current session.

Enforce in FindMatchingRule that a session rule only matches when its
session is the most recently created active session for the connecting
container. Tie-break on rowid because datetime('now') has second-level
precision and two sessions created back-to-back can share created_at.
@tito tito merged commit 4d124f4 into main Apr 14, 2026
3 checks passed
@tito tito deleted the mathieu/session-network-rules branch April 14, 2026 13:53
@tito tito mentioned this pull request Apr 14, 2026
2 tasks
tito added a commit that referenced this pull request Apr 14, 2026
## Summary
- Document the session/global/built-in source layers in `rules.md`,
including the resolution order and the "current session per container"
invariant added in #48.
- Document how greywall's profile network rules become session-scoped
rules in `using-with-greywall.md`, and explain how `--no-network-rules`
interacts with session supersession.

## Test plan
- [x] Verify both pages render via local Docusaurus build (or visual
inspection of the markdown)
- [x] Cross-link from the matching greywall PR
(GreyhavenHQ/greywall#80) once both land
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant