fix auto approver on register and new policy (#2506)
* fix issue auto approve route on register bug This commit fixes an issue where routes where not approved on a node during registration. This cause the auto approval to require the node to readvertise the routes. Fixes #2497 Fixes #2485 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * hsic: only set db policy if exist Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * policy: calculate changed based on policy and filter v1 is a bit simpler than v2, it does not pre calculate the auto approver map and we cannot tell if it is changed. Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
e3521be705
commit
5a18e91317
10 changed files with 575 additions and 217 deletions
|
@ -13,6 +13,7 @@ import (
|
|||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
|
@ -768,178 +769,6 @@ func TestHASubnetRouterFailover(t *testing.T) {
|
|||
assertTracerouteViaIP(t, tr, subRouter2.MustIPv4())
|
||||
}
|
||||
|
||||
func TestEnableDisableAutoApprovedRoute(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
t.Parallel()
|
||||
|
||||
expectedRoutes := "172.0.0.0/24"
|
||||
|
||||
spec := ScenarioSpec{
|
||||
NodesPerUser: 1,
|
||||
Users: []string{"user1"},
|
||||
}
|
||||
|
||||
scenario, err := NewScenario(spec)
|
||||
require.NoErrorf(t, err, "failed to create scenario: %s", err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithTags([]string{"tag:approve"}),
|
||||
tsic.WithAcceptRoutes(),
|
||||
}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:approve": {"user1@"},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
expectedRoutes: {"tag:approve"},
|
||||
},
|
||||
},
|
||||
},
|
||||
))
|
||||
assertNoErrHeadscaleEnv(t, err)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
assertNoErrListClients(t, err)
|
||||
|
||||
err = scenario.WaitForTailscaleSync()
|
||||
assertNoErrSync(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
assertNoErrGetHeadscale(t, err)
|
||||
|
||||
subRouter1 := allClients[0]
|
||||
|
||||
// Initially advertise route
|
||||
command := []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + expectedRoutes,
|
||||
}
|
||||
_, _, err = subRouter1.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
nodes, err := headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, nodes, 1)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
|
||||
// Stop advertising route
|
||||
command = []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
`--advertise-routes=`,
|
||||
}
|
||||
_, _, err = subRouter1.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to remove advertised route: %s", err)
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, nodes, 1)
|
||||
assertNodeRouteCount(t, nodes[0], 0, 1, 0)
|
||||
|
||||
// Advertise route again
|
||||
command = []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + expectedRoutes,
|
||||
}
|
||||
_, _, err = subRouter1.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, nodes, 1)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
}
|
||||
|
||||
func TestAutoApprovedSubRoute2068(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
t.Parallel()
|
||||
|
||||
expectedRoutes := "10.42.7.0/24"
|
||||
|
||||
user := "user1"
|
||||
|
||||
spec := ScenarioSpec{
|
||||
NodesPerUser: 1,
|
||||
Users: []string{user},
|
||||
}
|
||||
|
||||
scenario, err := NewScenario(spec)
|
||||
require.NoErrorf(t, err, "failed to create scenario: %s", err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithTags([]string{"tag:approve"}),
|
||||
tsic.WithAcceptRoutes(),
|
||||
},
|
||||
hsic.WithTestName("clienableroute"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithACLPolicy(
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:approve": {user + "@"},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
"10.42.0.0/16": {"tag:approve"},
|
||||
},
|
||||
},
|
||||
},
|
||||
))
|
||||
assertNoErrHeadscaleEnv(t, err)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
assertNoErrListClients(t, err)
|
||||
|
||||
err = scenario.WaitForTailscaleSync()
|
||||
assertNoErrSync(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
assertNoErrGetHeadscale(t, err)
|
||||
|
||||
subRouter1 := allClients[0]
|
||||
|
||||
// Initially advertise route
|
||||
command := []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + expectedRoutes,
|
||||
}
|
||||
_, _, err = subRouter1.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(10 * time.Second)
|
||||
|
||||
nodes, err := headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, nodes, 1)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
}
|
||||
|
||||
// TestSubnetRouteACL verifies that Subnet routes are distributed
|
||||
// as expected when ACLs are activated.
|
||||
// It implements the issue from
|
||||
|
@ -1390,7 +1219,6 @@ func TestSubnetRouterMultiNetwork(t *testing.T) {
|
|||
assertTracerouteViaIP(t, tr, user1c.MustIPv4())
|
||||
}
|
||||
|
||||
// TestSubnetRouterMultiNetworkExitNode
|
||||
func TestSubnetRouterMultiNetworkExitNode(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
t.Parallel()
|
||||
|
@ -1469,10 +1297,7 @@ func TestSubnetRouterMultiNetworkExitNode(t *testing.T) {
|
|||
}
|
||||
|
||||
// Enable route
|
||||
_, err = headscale.ApproveRoutes(
|
||||
nodes[0].Id,
|
||||
[]netip.Prefix{tsaddr.AllIPv4()},
|
||||
)
|
||||
_, err = headscale.ApproveRoutes(nodes[0].Id, []netip.Prefix{tsaddr.AllIPv4()})
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
@ -1524,6 +1349,380 @@ func TestSubnetRouterMultiNetworkExitNode(t *testing.T) {
|
|||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
// TestAutoApproveMultiNetwork tests auto approving of routes
|
||||
// by setting up two networks where network1 has three subnet
|
||||
// routers:
|
||||
// - routerUsernet1: advertising the docker network
|
||||
// - routerSubRoute: advertising a subroute, a /24 inside a auto approved /16
|
||||
// - routeExitNode: advertising an exit node
|
||||
//
|
||||
// Each router is tested step by step through the following scenarios
|
||||
// - Policy is set to auto approve the nodes route
|
||||
// - Node advertises route and it is verified that it is auto approved and sent to nodes
|
||||
// - Policy is changed to _not_ auto approve the route
|
||||
// - Verify that peers can still see the node
|
||||
// - Disable route, making it unavailable
|
||||
// - Verify that peers can no longer use node
|
||||
// - Policy is changed back to auto approve route, check that routes already existing is approved.
|
||||
// - Verify that routes can now be seen by peers.
|
||||
func TestAutoApproveMultiNetwork(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
t.Parallel()
|
||||
|
||||
spec := ScenarioSpec{
|
||||
NodesPerUser: 3,
|
||||
Users: []string{"user1", "user2"},
|
||||
Networks: map[string][]string{
|
||||
"usernet1": {"user1"},
|
||||
"usernet2": {"user2"},
|
||||
},
|
||||
ExtraService: map[string][]extraServiceFunc{
|
||||
"usernet1": {Webservice},
|
||||
},
|
||||
// We build the head image with curl and traceroute, so only use
|
||||
// that for this test.
|
||||
Versions: []string{"head"},
|
||||
}
|
||||
|
||||
rootRoute := netip.MustParsePrefix("10.42.0.0/16")
|
||||
subRoute := netip.MustParsePrefix("10.42.7.0/24")
|
||||
notApprovedRoute := netip.MustParsePrefix("192.168.0.0/24")
|
||||
|
||||
scenario, err := NewScenario(spec)
|
||||
require.NoErrorf(t, err, "failed to create scenario: %s", err)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
||||
pol := &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:approve": {"user1@"},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
rootRoute.String(): {"tag:approve"},
|
||||
},
|
||||
ExitNode: []string{"tag:approve"},
|
||||
},
|
||||
}
|
||||
|
||||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithAcceptRoutes(),
|
||||
tsic.WithTags([]string{"tag:approve"}),
|
||||
},
|
||||
hsic.WithTestName("clienableroute"),
|
||||
hsic.WithEmbeddedDERPServerOnly(),
|
||||
hsic.WithTLS(),
|
||||
hsic.WithACLPolicy(pol),
|
||||
hsic.WithPolicyMode(types.PolicyModeDB),
|
||||
)
|
||||
assertNoErrHeadscaleEnv(t, err)
|
||||
|
||||
allClients, err := scenario.ListTailscaleClients()
|
||||
assertNoErrListClients(t, err)
|
||||
|
||||
err = scenario.WaitForTailscaleSync()
|
||||
assertNoErrSync(t, err)
|
||||
|
||||
headscale, err := scenario.Headscale()
|
||||
assertNoErrGetHeadscale(t, err)
|
||||
assert.NotNil(t, headscale)
|
||||
|
||||
route, err := scenario.SubnetOfNetwork("usernet1")
|
||||
require.NoError(t, err)
|
||||
|
||||
// Set the route of usernet1 to be autoapproved
|
||||
pol.AutoApprovers.Routes[route.String()] = []string{"tag:approve"}
|
||||
err = headscale.SetPolicy(pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
services, err := scenario.Services("usernet1")
|
||||
require.NoError(t, err)
|
||||
require.Len(t, services, 1)
|
||||
|
||||
usernet1, err := scenario.Network("usernet1")
|
||||
require.NoError(t, err)
|
||||
|
||||
web := services[0]
|
||||
webip := netip.MustParseAddr(web.GetIPInNetwork(usernet1))
|
||||
weburl := fmt.Sprintf("http://%s/etc/hostname", webip)
|
||||
t.Logf("webservice: %s, %s", webip.String(), weburl)
|
||||
|
||||
// Sort nodes by ID
|
||||
sort.SliceStable(allClients, func(i, j int) bool {
|
||||
statusI := allClients[i].MustStatus()
|
||||
statusJ := allClients[j].MustStatus()
|
||||
|
||||
return statusI.Self.ID < statusJ.Self.ID
|
||||
})
|
||||
|
||||
// This is ok because the scenario makes users in order, so the three first
|
||||
// nodes, which are subnet routes, will be created first, and the last user
|
||||
// will be created with the second.
|
||||
routerUsernet1 := allClients[0]
|
||||
routerSubRoute := allClients[1]
|
||||
routerExitNode := allClients[2]
|
||||
|
||||
client := allClients[3]
|
||||
|
||||
// Advertise the route for the dockersubnet of user1
|
||||
command := []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + route.String(),
|
||||
}
|
||||
_, _, err = routerUsernet1.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err := headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err := client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
|
||||
url := fmt.Sprintf("http://%s/etc/hostname", webip)
|
||||
t.Logf("url from %s to %s", client.Hostname(), url)
|
||||
|
||||
result, err := client.Curl(url)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 13)
|
||||
|
||||
tr, err := client.Traceroute(webip)
|
||||
require.NoError(t, err)
|
||||
assertTracerouteViaIP(t, tr, routerUsernet1.MustIPv4())
|
||||
|
||||
// Remove the auto approval from the policy, any routes already enabled should be allowed.
|
||||
delete(pol.AutoApprovers.Routes, route.String())
|
||||
err = headscale.SetPolicy(pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
|
||||
url = fmt.Sprintf("http://%s/etc/hostname", webip)
|
||||
t.Logf("url from %s to %s", client.Hostname(), url)
|
||||
|
||||
result, err = client.Curl(url)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 13)
|
||||
|
||||
tr, err = client.Traceroute(webip)
|
||||
require.NoError(t, err)
|
||||
assertTracerouteViaIP(t, tr, routerUsernet1.MustIPv4())
|
||||
|
||||
// Disable the route, making it unavailable since it is no longer auto-approved
|
||||
_, err = headscale.ApproveRoutes(
|
||||
nodes[0].GetId(),
|
||||
[]netip.Prefix{},
|
||||
)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 0, 0)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
|
||||
// Add the route back to the auto approver in the policy, the route should
|
||||
// now become available again.
|
||||
pol.AutoApprovers.Routes[route.String()] = []string{"tag:approve"}
|
||||
err = headscale.SetPolicy(pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
require.NotNil(t, peerStatus.PrimaryRoutes)
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
|
||||
url = fmt.Sprintf("http://%s/etc/hostname", webip)
|
||||
t.Logf("url from %s to %s", client.Hostname(), url)
|
||||
|
||||
result, err = client.Curl(url)
|
||||
require.NoError(t, err)
|
||||
assert.Len(t, result, 13)
|
||||
|
||||
tr, err = client.Traceroute(webip)
|
||||
require.NoError(t, err)
|
||||
assertTracerouteViaIP(t, tr, routerUsernet1.MustIPv4())
|
||||
|
||||
// Advertise and validate a subnet of an auto approved route, /24 inside the
|
||||
// auto approved /16.
|
||||
command = []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + subRoute.String(),
|
||||
}
|
||||
_, _, err = routerSubRoute.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
assertNodeRouteCount(t, nodes[1], 1, 1, 1)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else if peerStatus.ID == "2" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), subRoute)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{subRoute})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Advertise a not approved route will not end up anywhere
|
||||
command = []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-routes=" + notApprovedRoute.String(),
|
||||
}
|
||||
_, _, err = routerSubRoute.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
// These route should auto approve, so the node is expected to have a route
|
||||
// for all counts.
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
assertNodeRouteCount(t, nodes[1], 1, 1, 0)
|
||||
assertNodeRouteCount(t, nodes[2], 0, 0, 0)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// Exit routes are also automatically approved
|
||||
command = []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
"--advertise-exit-node",
|
||||
}
|
||||
_, _, err = routerExitNode.Execute(command)
|
||||
require.NoErrorf(t, err, "failed to advertise route: %s", err)
|
||||
|
||||
time.Sleep(5 * time.Second)
|
||||
|
||||
nodes, err = headscale.ListNodes()
|
||||
require.NoError(t, err)
|
||||
assertNodeRouteCount(t, nodes[0], 1, 1, 1)
|
||||
assertNodeRouteCount(t, nodes[1], 1, 1, 0)
|
||||
assertNodeRouteCount(t, nodes[2], 2, 2, 2)
|
||||
|
||||
// Verify that the routes have been sent to the client.
|
||||
status, err = client.Status()
|
||||
require.NoError(t, err)
|
||||
|
||||
for _, peerKey := range status.Peers() {
|
||||
peerStatus := status.Peer[peerKey]
|
||||
|
||||
if peerStatus.ID == "1" {
|
||||
assert.Contains(t, peerStatus.PrimaryRoutes.AsSlice(), *route)
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{*route})
|
||||
} else if peerStatus.ID == "3" {
|
||||
requirePeerSubnetRoutes(t, peerStatus, []netip.Prefix{tsaddr.AllIPv4(), tsaddr.AllIPv6()})
|
||||
} else {
|
||||
requirePeerSubnetRoutes(t, peerStatus, nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func assertTracerouteViaIP(t *testing.T, tr util.Traceroute, ip netip.Addr) {
|
||||
t.Helper()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue