Skip to content

feat(acl): Introduction of reachability map - #604

Draft
bufferpurge wants to merge 2 commits into
tale:mainfrom
bufferpurge:acl-interactive-map
Draft

feat(acl): Introduction of reachability map#604
bufferpurge wants to merge 2 commits into
tale:mainfrom
bufferpurge:acl-interactive-map

Conversation

@bufferpurge

Copy link
Copy Markdown

Relates to #603.

A read-only visual view of what the ACL policy actually permits: a map of machines with a line per permitted flow. A map is created consisting of nodes and lines are drawn between them in a "constellation" where lines or nodes can be filtered accordingly.

New — app/utils/acl/ (~930 lines, no server or React imports, so it runs in a loader or the browser)

  • parse.ts / hujson.ts — HuJSON → typed policy
  • resolve.ts — alias expansion: tag:, group: (recursive, cycle-guarded), autogroup:member/tagged/internet/self, hosts, IPv4 CIDRs
  • evaluate.tsevaluatePolicy(policy, nodes) → nodes, edges, per-edge rules, warnings
  • locate.ts — source offsets, for the jump-to-rule links

New — map.client.tsx

Changed (4 files)

  • acl-loader.ts — fetches machines for the map, gated on read_machines, in a try/catch so a failure degrades the map rather than the editor
  • overview.tsx — the new tab; tabs become URL-controlled so jump-to-rule is a real history entry; Save/Discard hidden on the map tab only
  • cm.client.tsx — optional highlight prop so the editor can reveal a rule (selection and scroll only, never a document change)
  • package.json — adds @xyflow/react

Notes

  • Strictly read-only: the component has three props and no callbacks, contains no fetch/submit primitive, and its only outward channel is useSearchParams (GET). Nothing here can reach the ACL write path.
  • Shows the saved policy, with a banner and disabled jump links while the editor has unsaved changes.

Testing — 44 new unit tests (261 total, all passing). pnpm typecheck, lint and build clean.

What the map does

  • Evaluates the policy. Resolves every acls[] rule against the live machine list — tags, groups (recursive), autogroup:member/tagged/internet/self, host aliases, IPv4 CIDRs — into a graph of permitted flows. Internet and off-mesh subnets appear as pseudo-nodes, subnets carrying the routers that serve them.
  • Overview. All machines on a ring, one line per permitted direction. Hovering a machine highlights its flows in the legend's colours.
  • Filtering by clicking. Click a machine to add or remove it. One selected shows its whole world; two or more narrows to the traffic between them. Toolbar buttons suspend, clear, or hide everything else; a searchable picker (name, tag, owner or IP) does the same by hand.
  • Inspect. Focuses one machine into lanes — reached-by on the left, can-reach on the right — with an inbound/outbound/all direction filter.
  • Rules panel. Click any flow for the rules permitting it: rule index, protocol, ports and the endpoints as the policy writes them. With machines selected it lists their flows grouped per conversation.
  • Jump to source. A magnifier on any rule or warning opens the Edit tab and selects that exact rule — or the offending token — in the policy file.
  • Warnings. Unresolved aliases, off-mesh sources and wildcard blow-ups are reported inline, each locatable in the file.

I have tested this against my own headscale instance - which means that more testing would be highly appreciated/required with other constellations of ACLs. I'm not sure if the "Preview rules" placeholder was supposed to be something like this. here are some screenshots:

Main overview:
map1

Pressing one machine shows the relationship it has to other machines, visually represented by both direction and color according to legend:
map2

Multiple machines can be pressed (filtered) to see whether they have any active ACL rules to each other:
map3

Inbound filter used when pressing one machine to see which machines can reach it:
map4

Machine inspect mode - for a more focused view on one machine:
map5

Checking outbound flows in the inspect mode:
map6

Multiple nodes selected/added to filter with the "Hide machines outside of the filter" toggle active:
map7

When the magnifying glass on a rule on the right-hand side is clicked, it directs to the related rule in the ACL editor:
map8

Representation of the filter dropdown menu:
map9

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