@@ -17,6 +17,8 @@ import (
17
17
"github.com/juanfont/headscale/integration/hsic"
18
18
"github.com/juanfont/headscale/integration/tsic"
19
19
"github.com/stretchr/testify/assert"
20
+ "github.com/stretchr/testify/require"
21
+ "tailscale.com/net/tsaddr"
20
22
"tailscale.com/types/ipproto"
21
23
"tailscale.com/types/views"
22
24
"tailscale.com/wgengine/filter"
@@ -1316,3 +1318,123 @@ func TestSubnetRouteACL(t *testing.T) {
1316
1318
t .Errorf ("Subnet (%s) filter, unexpected result (-want +got):\n %s" , subRouter1 .Hostname (), diff )
1317
1319
}
1318
1320
}
1321
+
1322
+ // TestEnablingExitRoutes tests enabling exit routes for clients.
1323
+ // Its more or less the same as TestEnablingRoutes, but with the --advertise-exit-node flag
1324
+ // set during login instead of set.
1325
+ func TestEnablingExitRoutes (t * testing.T ) {
1326
+ IntegrationSkip (t )
1327
+ t .Parallel ()
1328
+
1329
+ user := "user2"
1330
+
1331
+ scenario , err := NewScenario (dockertestMaxWait ())
1332
+ assertNoErrf (t , "failed to create scenario: %s" , err )
1333
+ defer scenario .ShutdownAssertNoPanics (t )
1334
+
1335
+ spec := map [string ]int {
1336
+ user : 2 ,
1337
+ }
1338
+
1339
+ err = scenario .CreateHeadscaleEnv (spec , []tsic.Option {
1340
+ tsic .WithExtraLoginArgs ([]string {"--advertise-exit-node" }),
1341
+ }, hsic .WithTestName ("clienableroute" ))
1342
+ assertNoErrHeadscaleEnv (t , err )
1343
+
1344
+ allClients , err := scenario .ListTailscaleClients ()
1345
+ assertNoErrListClients (t , err )
1346
+
1347
+ err = scenario .WaitForTailscaleSync ()
1348
+ assertNoErrSync (t , err )
1349
+
1350
+ headscale , err := scenario .Headscale ()
1351
+ assertNoErrGetHeadscale (t , err )
1352
+
1353
+ err = scenario .WaitForTailscaleSync ()
1354
+ assertNoErrSync (t , err )
1355
+
1356
+ var routes []* v1.Route
1357
+ err = executeAndUnmarshal (
1358
+ headscale ,
1359
+ []string {
1360
+ "headscale" ,
1361
+ "routes" ,
1362
+ "list" ,
1363
+ "--output" ,
1364
+ "json" ,
1365
+ },
1366
+ & routes ,
1367
+ )
1368
+
1369
+ assertNoErr (t , err )
1370
+ assert .Len (t , routes , 4 )
1371
+
1372
+ for _ , route := range routes {
1373
+ assert .True (t , route .GetAdvertised ())
1374
+ assert .False (t , route .GetEnabled ())
1375
+ assert .False (t , route .GetIsPrimary ())
1376
+ }
1377
+
1378
+ // Verify that no routes has been sent to the client,
1379
+ // they are not yet enabled.
1380
+ for _ , client := range allClients {
1381
+ status , err := client .Status ()
1382
+ assertNoErr (t , err )
1383
+
1384
+ for _ , peerKey := range status .Peers () {
1385
+ peerStatus := status .Peer [peerKey ]
1386
+
1387
+ assert .Nil (t , peerStatus .PrimaryRoutes )
1388
+ }
1389
+ }
1390
+
1391
+ // Enable all routes
1392
+ for _ , route := range routes {
1393
+ _ , err = headscale .Execute (
1394
+ []string {
1395
+ "headscale" ,
1396
+ "routes" ,
1397
+ "enable" ,
1398
+ "--route" ,
1399
+ strconv .Itoa (int (route .GetId ())),
1400
+ })
1401
+ assertNoErr (t , err )
1402
+ }
1403
+
1404
+ var enablingRoutes []* v1.Route
1405
+ err = executeAndUnmarshal (
1406
+ headscale ,
1407
+ []string {
1408
+ "headscale" ,
1409
+ "routes" ,
1410
+ "list" ,
1411
+ "--output" ,
1412
+ "json" ,
1413
+ },
1414
+ & enablingRoutes ,
1415
+ )
1416
+ assertNoErr (t , err )
1417
+ assert .Len (t , enablingRoutes , 4 )
1418
+
1419
+ for _ , route := range enablingRoutes {
1420
+ assert .True (t , route .GetAdvertised ())
1421
+ assert .True (t , route .GetEnabled ())
1422
+ }
1423
+
1424
+ time .Sleep (5 * time .Second )
1425
+
1426
+ // Verify that the clients can see the new routes
1427
+ for _ , client := range allClients {
1428
+ status , err := client .Status ()
1429
+ assertNoErr (t , err )
1430
+
1431
+ for _ , peerKey := range status .Peers () {
1432
+ peerStatus := status .Peer [peerKey ]
1433
+
1434
+ require .NotNil (t , peerStatus .AllowedIPs )
1435
+ assert .Len (t , peerStatus .AllowedIPs .AsSlice (), 4 )
1436
+ assert .Contains (t , peerStatus .AllowedIPs .AsSlice (), tsaddr .AllIPv4 ())
1437
+ assert .Contains (t , peerStatus .AllowedIPs .AsSlice (), tsaddr .AllIPv6 ())
1438
+ }
1439
+ }
1440
+ }
0 commit comments