1
0
mirror of https://github.com/juanfont/headscale.git synced 2025-09-02 13:47:00 +02:00

chop chop

Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
Kristoffer Dalby 2025-02-13 15:38:25 +01:00
parent 45566cc11d
commit fe9557a729
No known key found for this signature in database
7 changed files with 169 additions and 177 deletions

View File

@ -87,16 +87,13 @@ func (h *Headscale) handleExistingNode(
// If the request expiry is in the past, we consider it a logout. // If the request expiry is in the past, we consider it a logout.
if requestExpiry.Before(time.Now()) { if requestExpiry.Before(time.Now()) {
if node.IsEphemeral() { if node.IsEphemeral() {
changedNodes, err := h.db.DeleteNode(node, h.nodeNotifier.LikelyConnectedMap()) err := h.db.DeleteNode(node)
if err != nil { if err != nil {
return nil, fmt.Errorf("deleting ephemeral node: %w", err) return nil, fmt.Errorf("deleting ephemeral node: %w", err)
} }
ctx := types.NotifyCtx(context.Background(), "logout-ephemeral", "na") ctx := types.NotifyCtx(context.Background(), "logout-ephemeral", "na")
h.nodeNotifier.NotifyAll(ctx, types.UpdatePeerRemoved(node.ID)) h.nodeNotifier.NotifyAll(ctx, types.UpdatePeerRemoved(node.ID))
if changedNodes != nil {
h.nodeNotifier.NotifyAll(ctx, types.UpdatePeerChanged(changedNodes...))
}
} }
expired = true expired = true

View File

@ -454,3 +454,32 @@ func TestMigrationsPostgres(t *testing.T) {
}) })
} }
} }
func dbForTest(t *testing.T, testName string) *HSDatabase {
t.Helper()
tmpDir, err := os.MkdirTemp("", testName)
if err != nil {
t.Fatalf("creating tempdir: %s", err)
}
dbPath := tmpDir + "/headscale_test.db"
db, err = NewHeadscaleDatabase(
types.DatabaseConfig{
Type: "sqlite3",
Sqlite: types.SqliteConfig{
Path: dbPath,
},
},
"",
emptyCache(),
)
if err != nil {
t.Fatalf("setting up database: %s", err)
}
t.Logf("database set up at: %s", dbPath)
return db
}

View File

@ -19,8 +19,6 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"gopkg.in/check.v1" "gopkg.in/check.v1"
"gorm.io/gorm" "gorm.io/gorm"
"tailscale.com/net/tsaddr"
"tailscale.com/tailcfg"
"tailscale.com/types/key" "tailscale.com/types/key"
"tailscale.com/types/ptr" "tailscale.com/types/ptr"
) )
@ -457,142 +455,143 @@ func TestHeadscale_generateGivenName(t *testing.T) {
} }
} }
func TestAutoApproveRoutes(t *testing.T) { // TODO(kradalby): replace this test
tests := []struct { // func TestAutoApproveRoutes(t *testing.T) {
name string // tests := []struct {
acl string // name string
routes []netip.Prefix // acl string
want []netip.Prefix // routes []netip.Prefix
}{ // want []netip.Prefix
{ // }{
name: "2068-approve-issue-sub", // {
acl: ` // name: "2068-approve-issue-sub",
{ // acl: `
"groups": { // {
"group:k8s": ["test"] // "groups": {
}, // "group:k8s": ["test"]
// },
"acls": [ // "acls": [
{"action": "accept", "users": ["*"], "ports": ["*:*"]}, // {"action": "accept", "users": ["*"], "ports": ["*:*"]},
], // ],
"autoApprovers": { // "autoApprovers": {
"routes": { // "routes": {
"10.42.0.0/16": ["test"], // "10.42.0.0/16": ["test"],
} // }
} // }
}`, // }`,
routes: []netip.Prefix{netip.MustParsePrefix("10.42.7.0/24")}, // routes: []netip.Prefix{netip.MustParsePrefix("10.42.7.0/24")},
want: []netip.Prefix{netip.MustParsePrefix("10.42.7.0/24")}, // want: []netip.Prefix{netip.MustParsePrefix("10.42.7.0/24")},
}, // },
{ // {
name: "2068-approve-issue-sub", // name: "2068-approve-issue-sub",
acl: ` // acl: `
{ // {
"tagOwners": { // "tagOwners": {
"tag:exit": ["test"], // "tag:exit": ["test"],
}, // },
"groups": { // "groups": {
"group:test": ["test"] // "group:test": ["test"]
}, // },
"acls": [ // "acls": [
{"action": "accept", "users": ["*"], "ports": ["*:*"]}, // {"action": "accept", "users": ["*"], "ports": ["*:*"]},
], // ],
"autoApprovers": { // "autoApprovers": {
"exitNode": ["tag:exit"], // "exitNode": ["tag:exit"],
"routes": { // "routes": {
"10.10.0.0/16": ["group:test"], // "10.10.0.0/16": ["group:test"],
"10.11.0.0/16": ["test"], // "10.11.0.0/16": ["test"],
} // }
} // }
}`, // }`,
routes: []netip.Prefix{ // routes: []netip.Prefix{
tsaddr.AllIPv4(), // tsaddr.AllIPv4(),
tsaddr.AllIPv6(), // tsaddr.AllIPv6(),
netip.MustParsePrefix("10.10.0.0/16"), // netip.MustParsePrefix("10.10.0.0/16"),
netip.MustParsePrefix("10.11.0.0/24"), // netip.MustParsePrefix("10.11.0.0/24"),
}, // },
want: []netip.Prefix{ // want: []netip.Prefix{
tsaddr.AllIPv4(), // tsaddr.AllIPv4(),
netip.MustParsePrefix("10.10.0.0/16"), // netip.MustParsePrefix("10.10.0.0/16"),
netip.MustParsePrefix("10.11.0.0/24"), // netip.MustParsePrefix("10.11.0.0/24"),
tsaddr.AllIPv6(), // tsaddr.AllIPv6(),
}, // },
}, // },
} // }
for _, tt := range tests { // for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { // t.Run(tt.name, func(t *testing.T) {
adb, err := newSQLiteTestDB() // adb, err := newSQLiteTestDB()
require.NoError(t, err) // require.NoError(t, err)
pol, err := policy.LoadACLPolicyFromBytes([]byte(tt.acl)) // pol, err := policy.LoadACLPolicyFromBytes([]byte(tt.acl))
require.NoError(t, err) // require.NoError(t, err)
require.NotNil(t, pol) // require.NotNil(t, pol)
user, err := adb.CreateUser(types.User{Name: "test"}) // user, err := adb.CreateUser(types.User{Name: "test"})
require.NoError(t, err) // require.NoError(t, err)
pak, err := adb.CreatePreAuthKey(types.UserID(user.ID), false, false, nil, nil) // pak, err := adb.CreatePreAuthKey(types.UserID(user.ID), false, false, nil, nil)
require.NoError(t, err) // require.NoError(t, err)
nodeKey := key.NewNode() // nodeKey := key.NewNode()
machineKey := key.NewMachine() // machineKey := key.NewMachine()
v4 := netip.MustParseAddr("100.64.0.1") // v4 := netip.MustParseAddr("100.64.0.1")
node := types.Node{ // node := types.Node{
ID: 0, // ID: 0,
MachineKey: machineKey.Public(), // MachineKey: machineKey.Public(),
NodeKey: nodeKey.Public(), // NodeKey: nodeKey.Public(),
Hostname: "test", // Hostname: "test",
UserID: user.ID, // UserID: user.ID,
RegisterMethod: util.RegisterMethodAuthKey, // RegisterMethod: util.RegisterMethodAuthKey,
AuthKeyID: ptr.To(pak.ID), // AuthKeyID: ptr.To(pak.ID),
Hostinfo: &tailcfg.Hostinfo{ // Hostinfo: &tailcfg.Hostinfo{
RequestTags: []string{"tag:exit"}, // RequestTags: []string{"tag:exit"},
RoutableIPs: tt.routes, // RoutableIPs: tt.routes,
}, // },
IPv4: &v4, // IPv4: &v4,
} // }
trx := adb.DB.Save(&node) // trx := adb.DB.Save(&node)
require.NoError(t, trx.Error) // require.NoError(t, trx.Error)
sendUpdate, err := adb.SaveNodeRoutes(&node) // sendUpdate, err := adb.SaveNodeRoutes(&node)
require.NoError(t, err) // require.NoError(t, err)
assert.False(t, sendUpdate) // assert.False(t, sendUpdate)
node0ByID, err := adb.GetNodeByID(0) // node0ByID, err := adb.GetNodeByID(0)
require.NoError(t, err) // require.NoError(t, err)
users, err := adb.ListUsers() // users, err := adb.ListUsers()
assert.NoError(t, err) // assert.NoError(t, err)
nodes, err := adb.ListNodes() // nodes, err := adb.ListNodes()
assert.NoError(t, err) // assert.NoError(t, err)
pm, err := policy.NewPolicyManager([]byte(tt.acl), users, nodes) // pm, err := policy.NewPolicyManager([]byte(tt.acl), users, nodes)
assert.NoError(t, err) // assert.NoError(t, err)
// TODO(kradalby): Check state update // // TODO(kradalby): Check state update
err = adb.EnableAutoApprovedRoutes(pm, node0ByID) // err = adb.EnableAutoApprovedRoutes(pm, node0ByID)
require.NoError(t, err) // require.NoError(t, err)
enabledRoutes, err := adb.GetEnabledRoutes(node0ByID) // enabledRoutes, err := adb.GetEnabledRoutes(node0ByID)
require.NoError(t, err) // require.NoError(t, err)
assert.Len(t, enabledRoutes, len(tt.want)) // assert.Len(t, enabledRoutes, len(tt.want))
tsaddr.SortPrefixes(enabledRoutes) // tsaddr.SortPrefixes(enabledRoutes)
if diff := cmp.Diff(tt.want, enabledRoutes, util.Comparers...); diff != "" { // if diff := cmp.Diff(tt.want, enabledRoutes, util.Comparers...); diff != "" {
t.Errorf("unexpected enabled routes (-want +got):\n%s", diff) // t.Errorf("unexpected enabled routes (-want +got):\n%s", diff)
} // }
}) // })
} // }
} // }
func TestEphemeralGarbageCollectorOrder(t *testing.T) { func TestEphemeralGarbageCollectorOrder(t *testing.T) {
want := []types.NodeID{1, 3} want := []types.NodeID{1, 3}

View File

@ -182,28 +182,15 @@ func Test_fullMapResponse(t *testing.T) {
AuthKey: &types.PreAuthKey{}, AuthKey: &types.PreAuthKey{},
LastSeen: &lastSeen, LastSeen: &lastSeen,
Expiry: &expire, Expiry: &expire,
Hostinfo: &tailcfg.Hostinfo{}, Hostinfo: &tailcfg.Hostinfo{
Routes: []types.Route{ RoutableIPs: []netip.Prefix{
{ tsaddr.AllIPv4(),
Prefix: tsaddr.AllIPv4(), netip.MustParsePrefix("192.168.0.0/24"),
Advertised: true, netip.MustParsePrefix("172.0.0.0/10"),
Enabled: true,
IsPrimary: false,
},
{
Prefix: netip.MustParsePrefix("192.168.0.0/24"),
Advertised: true,
Enabled: true,
IsPrimary: true,
},
{
Prefix: netip.MustParsePrefix("172.0.0.0/10"),
Advertised: true,
Enabled: false,
IsPrimary: true,
}, },
}, },
CreatedAt: created, ApprovedRoutes: []netip.Prefix{tsaddr.AllIPv4(), netip.MustParsePrefix("192.168.0.0/24")},
CreatedAt: created,
} }
tailMini := &tailcfg.Node{ tailMini := &tailcfg.Node{
@ -263,7 +250,6 @@ func Test_fullMapResponse(t *testing.T) {
LastSeen: &lastSeen, LastSeen: &lastSeen,
Expiry: &expire, Expiry: &expire,
Hostinfo: &tailcfg.Hostinfo{}, Hostinfo: &tailcfg.Hostinfo{},
Routes: []types.Route{},
CreatedAt: created, CreatedAt: created,
} }
@ -319,7 +305,6 @@ func Test_fullMapResponse(t *testing.T) {
LastSeen: &lastSeen, LastSeen: &lastSeen,
Expiry: &expire, Expiry: &expire,
Hostinfo: &tailcfg.Hostinfo{}, Hostinfo: &tailcfg.Hostinfo{},
Routes: []types.Route{},
CreatedAt: created, CreatedAt: created,
} }

View File

@ -107,28 +107,15 @@ func TestTailNode(t *testing.T) {
AuthKey: &types.PreAuthKey{}, AuthKey: &types.PreAuthKey{},
LastSeen: &lastSeen, LastSeen: &lastSeen,
Expiry: &expire, Expiry: &expire,
Hostinfo: &tailcfg.Hostinfo{}, Hostinfo: &tailcfg.Hostinfo{
Routes: []types.Route{ RoutableIPs: []netip.Prefix{
{ tsaddr.AllIPv4(),
Prefix: tsaddr.AllIPv4(), netip.MustParsePrefix("192.168.0.0/24"),
Advertised: true, netip.MustParsePrefix("172.0.0.0/10"),
Enabled: true,
IsPrimary: false,
},
{
Prefix: netip.MustParsePrefix("192.168.0.0/24"),
Advertised: true,
Enabled: true,
IsPrimary: true,
},
{
Prefix: netip.MustParsePrefix("172.0.0.0/10"),
Advertised: true,
Enabled: false,
IsPrimary: true,
}, },
}, },
CreatedAt: created, ApprovedRoutes: []netip.Prefix{tsaddr.AllIPv4(), netip.MustParsePrefix("192.168.0.0/24")},
CreatedAt: created,
}, },
pol: &policy.ACLPolicy{}, pol: &policy.ACLPolicy{},
dnsConfig: &tailcfg.DNSConfig{}, dnsConfig: &tailcfg.DNSConfig{},

View File

@ -3475,14 +3475,10 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPv4: iap("100.64.0.2"), IPv4: iap("100.64.0.2"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: types.User{Name: "router"},
Routes: types.Routes{ Hostinfo: &tailcfg.Hostinfo{
types.Route{ RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
NodeID: 2,
Prefix: netip.MustParsePrefix("10.33.0.0/16"),
IsPrimary: true,
Enabled: true,
},
}, },
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
}, },
}, },
rules: []tailcfg.FilterRule{ rules: []tailcfg.FilterRule{
@ -3508,14 +3504,10 @@ func Test_getFilteredByACLPeers(t *testing.T) {
IPv4: iap("100.64.0.2"), IPv4: iap("100.64.0.2"),
Hostname: "router", Hostname: "router",
User: types.User{Name: "router"}, User: types.User{Name: "router"},
Routes: types.Routes{ Hostinfo: &tailcfg.Hostinfo{
types.Route{ RoutableIPs: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
NodeID: 2,
Prefix: netip.MustParsePrefix("10.33.0.0/16"),
IsPrimary: true,
Enabled: true,
},
}, },
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("10.33.0.0/16")},
}, },
}, },
}, },

View File

@ -26,3 +26,6 @@ type Route struct {
// when the server is up. // when the server is up.
IsPrimary bool IsPrimary bool
} }
// DEPRECATED: Approval of routes is denormalised onto the relevant node.
type Routes []Route