mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 04:34:07 +09:00
policy/v2: keep withdrawn approved routes in wildcard sources
As SaaS, which holds them until an admin removes the approval.
This commit is contained in:
1 parent
d2a85b1d16
commit
420293cecf
3 files changed
+39
-4
No files matched your search
@@ -44,6 +44,11 @@ func TestApprovedSubnetRoutesIgnoreNodeOrder(t *testing.T) {
|
||||
want := []string{"10.1.0.0/16", "10.2.0.0/16"}
|
||||
assert.Equal(t, want, approvedSubnetRoutes(types.Nodes{a, b}.ViewSlice()))
|
||||
assert.Equal(t, want, approvedSubnetRoutes(types.Nodes{b, a}.ViewSlice()))
|
||||
|
||||
// A route stays after its node withdraws it, as on SaaS. An exit route stays out.
|
||||
b.Hostinfo = &tailcfg.Hostinfo{}
|
||||
b.ApprovedRoutes = append(b.ApprovedRoutes, netip.MustParsePrefix("0.0.0.0/0"))
|
||||
assert.Equal(t, want, approvedSubnetRoutes(types.Nodes{a, b}.ViewSlice()))
|
||||
}
|
||||
|
||||
func node(name, ipv4, ipv6 string, user types.User) *types.Node {
|
||||
|
||||
@@ -364,9 +364,10 @@ func (a Asterix) resolve(_ *Policy, _ types.Users, _ views.Slice[types.NodeView]
|
||||
return asterixResolved(), nil
|
||||
}
|
||||
|
||||
// approvedSubnetRoutes collects all approved non-exit subnet routes
|
||||
// advertised across all nodes. Per Tailscale documentation, wildcard
|
||||
// (*) SrcIPs include "any approved subnets".
|
||||
// approvedSubnetRoutes collects all approved non-exit subnet routes across all
|
||||
// nodes, advertised or not: SaaS keeps a route an admin approved after its node
|
||||
// withdraws it. Per Tailscale documentation, wildcard (*) SrcIPs include "any
|
||||
// approved subnets".
|
||||
//
|
||||
// These are collected separately from the Asterix IPSet because
|
||||
// IPSet merges overlapping ranges (e.g. 10.0.0.0/8 absorbs
|
||||
@@ -377,7 +378,11 @@ func approvedSubnetRoutes(nodes views.Slice[types.NodeView]) []string {
|
||||
var routes []string
|
||||
|
||||
for _, node := range nodes.All() {
|
||||
for _, route := range node.SubnetRoutes() {
|
||||
for _, route := range node.ApprovedRoutes().All() {
|
||||
if tsaddr.IsExitRoute(route) {
|
||||
continue
|
||||
}
|
||||
|
||||
s := route.String()
|
||||
if !seen.Contains(s) {
|
||||
seen.Add(s)
|
||||
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/juanfont/headscale/hscontrol/types/testcapture"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/key"
|
||||
"tailscale.com/types/netmap"
|
||||
@@ -183,6 +184,9 @@ func runRouteLifecycleCompat(t *testing.T, id, observer string, skips map[string
|
||||
|
||||
return "user " + nodes[0].User().Name()
|
||||
}},
|
||||
{"filter-routes", filterRouteSources(step.Captures[observer].Netmap), func() string {
|
||||
return filterRouteSources(r.clients[observer].Netmap())
|
||||
}},
|
||||
{"device", deviceState(
|
||||
countDevicesOnMachine(t, step, dev.MachineKey),
|
||||
dev.ID == join.saasID, sortedStrings(dev.Addresses) == join.saasAddrs,
|
||||
@@ -364,6 +368,27 @@ func (r *stepReplay) hsDeviceRoutes(t *testing.T, alias string) (deviceRoutes, b
|
||||
return out, true
|
||||
}
|
||||
|
||||
// filterRouteSources lists the sources in nm's packet filter that are no tailnet
|
||||
// addresses: the routes a wildcard source stands for.
|
||||
func filterRouteSources(nm *netmap.NetworkMap) string {
|
||||
if nm == nil {
|
||||
return "no netmap"
|
||||
}
|
||||
|
||||
seen := map[string]bool{}
|
||||
|
||||
for _, m := range nm.PacketFilter {
|
||||
for _, src := range m.Srcs {
|
||||
tailnet := tsaddr.CGNATRange().Contains(src.Addr()) || tsaddr.TailscaleULARange().Contains(src.Addr())
|
||||
if !tailnet {
|
||||
seen[src.String()] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return fmt.Sprint(slices.Sorted(maps.Keys(seen)))
|
||||
}
|
||||
|
||||
// saasDevice is the part of a SaaS device-list entry the checks read.
|
||||
// Keys and IDs are the capture's labels.
|
||||
type saasDevice struct {
|
||||
|
||||
Reference in new issue
Block a user