diff --git a/hscontrol/db/db.go b/hscontrol/db/db.go index 19bf942..b309f59 100644 --- a/hscontrol/db/db.go +++ b/hscontrol/db/db.go @@ -214,7 +214,7 @@ func NewHeadscaleDatabase( Msg("Failed to normalize machine hostname in DB migration") } - err = db.RenameMachine(&machines[item], normalizedHostname) + err = db.RenameMachine(machines[item], normalizedHostname) if err != nil { log.Error(). Caller(). diff --git a/hscontrol/db/machine.go b/hscontrol/db/machine.go index 033492e..60d93c9 100644 --- a/hscontrol/db/machine.go +++ b/hscontrol/db/machine.go @@ -123,7 +123,7 @@ func (hsdb *HSDatabase) GetMachine(user string, name string) (*types.Machine, er for _, m := range machines { if m.Hostname == name { - return &m, nil + return m, nil } } @@ -267,7 +267,7 @@ func (hsdb *HSDatabase) SetTags( hsdb.notifier.NotifyWithIgnore(types.StateUpdate{ Type: types.StatePeerChanged, - Changed: []uint64{machine.ID}, + Changed: types.Machines{machine}, }, machine.MachineKey) return nil @@ -303,7 +303,7 @@ func (hsdb *HSDatabase) RenameMachine(machine *types.Machine, newName string) er hsdb.notifier.NotifyWithIgnore(types.StateUpdate{ Type: types.StatePeerChanged, - Changed: []uint64{machine.ID}, + Changed: types.Machines{machine}, }, machine.MachineKey) return nil @@ -332,7 +332,7 @@ func (hsdb *HSDatabase) machineSetExpiry(machine *types.Machine, expiry time.Tim hsdb.notifier.NotifyWithIgnore(types.StateUpdate{ Type: types.StatePeerChanged, - Changed: []uint64{machine.ID}, + Changed: types.Machines{machine}, }, machine.MachineKey) return nil @@ -713,7 +713,7 @@ func (hsdb *HSDatabase) enableRoutes(machine *types.Machine, routeStrs ...string hsdb.notifier.NotifyWithIgnore(types.StateUpdate{ Type: types.StatePeerChanged, - Changed: []uint64{machine.ID}, + Changed: types.Machines{machine}, }, machine.MachineKey) return nil @@ -807,7 +807,7 @@ func (hsdb *HSDatabase) ExpireEphemeralMachines(inactivityThreshhold time.Durati Str("machine", machine.Hostname). Msg("Ephemeral client removed from database") - err = hsdb.deleteMachine(&machines[idx]) + err = hsdb.deleteMachine(machines[idx]) if err != nil { log.Error(). Err(err). @@ -860,7 +860,7 @@ func (hsdb *HSDatabase) ExpireExpiredMachines(lastCheck time.Time) time.Time { expired = append(expired, tailcfg.NodeID(machine.ID)) now := time.Now() - err := hsdb.machineSetExpiry(&machines[index], now) + err := hsdb.machineSetExpiry(machines[index], now) if err != nil { log.Error(). Err(err). diff --git a/hscontrol/db/machine_test.go b/hscontrol/db/machine_test.go index 7f837e0..0115ee9 100644 --- a/hscontrol/db/machine_test.go +++ b/hscontrol/db/machine_test.go @@ -590,7 +590,7 @@ func (s *Suite) TestAutoApproveRoutes(c *check.C) { db.db.Save(&machine) - err = db.ProcessMachineRoutes(&machine) + err = db.SaveMachineRoutes(&machine) c.Assert(err, check.IsNil) machine0ByID, err := db.GetMachineByID(0) diff --git a/hscontrol/db/routes.go b/hscontrol/db/routes.go index dfd01c8..834f53e 100644 --- a/hscontrol/db/routes.go +++ b/hscontrol/db/routes.go @@ -257,14 +257,16 @@ func (hsdb *HSDatabase) GetMachinePrimaryRoutes(machine *types.Machine) (types.R return routes, nil } -func (hsdb *HSDatabase) ProcessMachineRoutes(machine *types.Machine) error { +// SaveMachineRoutes takes a machine and updates the database with +// the new routes. +func (hsdb *HSDatabase) SaveMachineRoutes(machine *types.Machine) error { hsdb.mu.Lock() defer hsdb.mu.Unlock() - return hsdb.processMachineRoutes(machine) + return hsdb.saveMachineRoutes(machine) } -func (hsdb *HSDatabase) processMachineRoutes(machine *types.Machine) error { +func (hsdb *HSDatabase) saveMachineRoutes(machine *types.Machine) error { currentRoutes := types.Routes{} err := hsdb.db.Where("machine_id = ?", machine.ID).Find(¤tRoutes).Error if err != nil { @@ -332,7 +334,7 @@ func (hsdb *HSDatabase) handlePrimarySubnetFailover() error { log.Error().Err(err).Msg("error getting routes") } - changedMachines := make([]uint64, 0) + changedMachines := make(types.Machines, 0) for pos, route := range routes { if route.IsExitRoute() { continue @@ -353,7 +355,7 @@ func (hsdb *HSDatabase) handlePrimarySubnetFailover() error { return err } - changedMachines = append(changedMachines, route.MachineID) + changedMachines = append(changedMachines, &route.Machine) continue } @@ -427,7 +429,7 @@ func (hsdb *HSDatabase) handlePrimarySubnetFailover() error { return err } - changedMachines = append(changedMachines, route.MachineID) + changedMachines = append(changedMachines, &route.Machine) } } @@ -488,7 +490,7 @@ func (hsdb *HSDatabase) EnableAutoApprovedRoutes( approvedRoutes = append(approvedRoutes, advertisedRoute) } else { // TODO(kradalby): figure out how to get this to depend on less stuff - approvedIps, err := aclPolicy.ExpandAlias(types.Machines{*machine}, approvedAlias) + approvedIps, err := aclPolicy.ExpandAlias(types.Machines{machine}, approvedAlias) if err != nil { log.Err(err). Str("alias", approvedAlias). diff --git a/hscontrol/db/routes_test.go b/hscontrol/db/routes_test.go index 02313c1..4698be2 100644 --- a/hscontrol/db/routes_test.go +++ b/hscontrol/db/routes_test.go @@ -40,7 +40,7 @@ func (s *Suite) TestGetRoutes(c *check.C) { } db.db.Save(&machine) - err = db.ProcessMachineRoutes(&machine) + err = db.SaveMachineRoutes(&machine) c.Assert(err, check.IsNil) advertisedRoutes, err := db.GetAdvertisedRoutes(&machine) @@ -91,7 +91,7 @@ func (s *Suite) TestGetEnableRoutes(c *check.C) { } db.db.Save(&machine) - err = db.ProcessMachineRoutes(&machine) + err = db.SaveMachineRoutes(&machine) c.Assert(err, check.IsNil) availableRoutes, err := db.GetAdvertisedRoutes(&machine) @@ -165,7 +165,7 @@ func (s *Suite) TestIsUniquePrefix(c *check.C) { } db.db.Save(&machine1) - err = db.ProcessMachineRoutes(&machine1) + err = db.SaveMachineRoutes(&machine1) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine1, route.String()) @@ -190,7 +190,7 @@ func (s *Suite) TestIsUniquePrefix(c *check.C) { } db.db.Save(&machine2) - err = db.ProcessMachineRoutes(&machine2) + err = db.SaveMachineRoutes(&machine2) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine2, route2.String()) @@ -252,7 +252,7 @@ func (s *Suite) TestSubnetFailover(c *check.C) { } db.db.Save(&machine1) - err = db.ProcessMachineRoutes(&machine1) + err = db.SaveMachineRoutes(&machine1) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine1, prefix.String()) @@ -289,7 +289,7 @@ func (s *Suite) TestSubnetFailover(c *check.C) { } db.db.Save(&machine2) - err = db.ProcessMachineRoutes(&machine2) + err = db.SaveMachineRoutes(&machine2) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine2, prefix2.String()) @@ -337,7 +337,7 @@ func (s *Suite) TestSubnetFailover(c *check.C) { err = db.db.Save(&machine2).Error c.Assert(err, check.IsNil) - err = db.ProcessMachineRoutes(&machine2) + err = db.SaveMachineRoutes(&machine2) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine2, prefix.String()) @@ -394,7 +394,7 @@ func (s *Suite) TestDeleteRoutes(c *check.C) { } db.db.Save(&machine1) - err = db.ProcessMachineRoutes(&machine1) + err = db.SaveMachineRoutes(&machine1) c.Assert(err, check.IsNil) err = db.enableRoutes(&machine1, prefix.String()) diff --git a/hscontrol/grpcv1.go b/hscontrol/grpcv1.go index 292c8d8..c9ab516 100644 --- a/hscontrol/grpcv1.go +++ b/hscontrol/grpcv1.go @@ -342,7 +342,7 @@ func (api headscaleV1APIServer) ListMachines( for index, machine := range machines { m := machine.Proto() validTags, invalidTags := api.h.ACLPolicy.TagsOfMachine( - machine, + &machine, ) m.InvalidTags = invalidTags m.ValidTags = validTags diff --git a/hscontrol/mapper/mapper.go b/hscontrol/mapper/mapper.go index 97b0879..f5a2ddc 100644 --- a/hscontrol/mapper/mapper.go +++ b/hscontrol/mapper/mapper.go @@ -39,8 +39,6 @@ const ( var debugDumpMapResponsePath = envknob.String("HEADSCALE_DEBUG_DUMP_MAPRESPONSE_PATH") type Mapper struct { - db *db.HSDatabase - privateKey2019 *key.MachinePrivate isNoise bool @@ -55,11 +53,16 @@ type Mapper struct { uid string created time.Time seq uint64 + + // Map isnt concurrency safe, so we need to ensure + // only one func is accessing it over time. + mu sync.Mutex + peers map[uint64]*types.Machine } func NewMapper( machine *types.Machine, - db *db.HSDatabase, + peers types.Machines, privateKey *key.MachinePrivate, isNoise bool, derpMap *tailcfg.DERPMap, @@ -77,8 +80,6 @@ func NewMapper( uid, _ := util.GenerateRandomStringDNSSafe(mapperIDLength) return &Mapper{ - db: db, - privateKey2019: privateKey, isNoise: isNoise, @@ -91,6 +92,9 @@ func NewMapper( uid: uid, created: time.Now(), seq: 0, + + // TODO: populate + peers: peers.IDMap(), } } @@ -121,7 +125,7 @@ func fullMapResponse( logtail bool, randomClientPort bool, ) (*tailcfg.MapResponse, error) { - tailnode, err := tailNode(*machine, pol, dnsCfg, baseDomain) + tailnode, err := tailNode(machine, pol, dnsCfg, baseDomain) if err != nil { return nil, err } @@ -160,9 +164,7 @@ func fullMapResponse( } // Filter out peers that have expired. - peers = lo.Filter(peers, func(item types.Machine, index int) bool { - return !item.IsExpired() - }) + peers = filterExpiredAndNotReady(peers) // If there are filter rules present, see if there are any machines that cannot // access eachother at all and remove them from the peers. @@ -175,7 +177,7 @@ func fullMapResponse( dnsConfig := generateDNSConfig( dnsCfg, baseDomain, - *machine, + machine, peers, ) @@ -232,7 +234,7 @@ func generateUserProfiles( func generateDNSConfig( base *tailcfg.DNSConfig, baseDomain string, - machine types.Machine, + machine *types.Machine, peers types.Machines, ) *tailcfg.DNSConfig { dnsConfig := base.Clone() @@ -275,7 +277,7 @@ func generateDNSConfig( // // This will produce a resolver like: // `https://dns.nextdns.io/?device_name=node-name&device_model=linux&device_ip=100.64.0.1` -func addNextDNSMetadata(resolvers []*dnstype.Resolver, machine types.Machine) { +func addNextDNSMetadata(resolvers []*dnstype.Resolver, machine *types.Machine) { for _, resolver := range resolvers { if strings.HasPrefix(resolver.Addr, nextDNSDoHPrefix) { attrs := url.Values{ @@ -298,20 +300,13 @@ func (m *Mapper) FullMapResponse( machine *types.Machine, pol *policy.ACLPolicy, ) ([]byte, error) { - peers, err := m.db.ListPeers(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return nil, err - } + m.mu.Lock() + defer m.mu.Unlock() mapResponse, err := fullMapResponse( pol, machine, - peers, + machineMapToList(m.peers), m.baseDomain, m.dnsCfg, m.derpMap, @@ -382,42 +377,33 @@ func (m *Mapper) DERPMapResponse( func (m *Mapper) PeerChangedResponse( mapRequest tailcfg.MapRequest, machine *types.Machine, - machineIDs []uint64, + changed types.Machines, pol *policy.ACLPolicy, ) ([]byte, error) { + m.mu.Lock() + defer m.mu.Unlock() + var err error - changed := make(types.Machines, len(machineIDs)) lastSeen := make(map[tailcfg.NodeID]bool) - peersList, err := m.db.ListPeers(machine) - if err != nil { - return nil, err - } - - peers := peersList.IDMap() - - for idx, machineID := range machineIDs { - changed[idx] = peers[machineID] + // Update our internal map. + for _, machine := range changed { + m.peers[machine.ID] = machine // We have just seen the node, let the peers update their list. - lastSeen[tailcfg.NodeID(machineID)] = true + lastSeen[tailcfg.NodeID(machine.ID)] = true } rules, sshPolicy, err := policy.GenerateFilterAndSSHRules( pol, machine, - peersList, + machineMapToList(m.peers), ) if err != nil { return nil, err } - changed = lo.Filter(changed, func(item types.Machine, index int) bool { - // Filter out nodes that are expired OR - // nodes that has no endpoints, this typically means they have - // registered, but are not configured. - return !item.IsExpired() || len(item.Endpoints) > 0 - }) + changed = filterExpiredAndNotReady(changed) // If there are filter rules present, see if there are any machines that cannot // access eachother at all and remove them from the changed. @@ -449,6 +435,14 @@ func (m *Mapper) PeerRemovedResponse( machine *types.Machine, removed []tailcfg.NodeID, ) ([]byte, error) { + m.mu.Lock() + defer m.mu.Unlock() + + // remove from our internal map + for _, id := range removed { + delete(m.peers, uint64(id)) + } + resp := m.baseMapResponse(machine) resp.PeersRemoved = removed @@ -604,3 +598,22 @@ func (m *Mapper) baseMapResponse(_ *types.Machine) tailcfg.MapResponse { return resp } + +func machineMapToList(machines map[uint64]*types.Machine) types.Machines { + ret := make(types.Machines, 0) + + for _, machine := range machines { + ret = append(ret, machine) + } + + return ret +} + +func filterExpiredAndNotReady(peers types.Machines) types.Machines { + return lo.Filter(peers, func(item *types.Machine, index int) bool { + // Filter out nodes that are expired OR + // nodes that has no endpoints, this typically means they have + // registered, but are not configured. + return !item.IsExpired() || len(item.Endpoints) > 0 + }) +} diff --git a/hscontrol/mapper/mapper_test.go b/hscontrol/mapper/mapper_test.go index d325548..dd455d1 100644 --- a/hscontrol/mapper/mapper_test.go +++ b/hscontrol/mapper/mapper_test.go @@ -18,8 +18,8 @@ import ( ) func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { - mach := func(hostname, username string, userid uint) types.Machine { - return types.Machine{ + mach := func(hostname, username string, userid uint) *types.Machine { + return &types.Machine{ Hostname: hostname, UserID: userid, User: types.User{ @@ -34,7 +34,7 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) { machine2InShared1 := mach("test_get_shared_nodes_4", "user1", 1) userProfiles := generateUserProfiles( - &machineInShared1, + machineInShared1, types.Machines{ machineInShared2, machineInShared3, machine2InShared1, }, @@ -91,8 +91,8 @@ func TestDNSConfigMapResponse(t *testing.T) { for _, tt := range tests { t.Run(fmt.Sprintf("with-magicdns-%v", tt.magicDNS), func(t *testing.T) { - mach := func(hostname, username string, userid uint) types.Machine { - return types.Machine{ + mach := func(hostname, username string, userid uint) *types.Machine { + return &types.Machine{ Hostname: hostname, UserID: userid, User: types.User{ @@ -243,7 +243,7 @@ func Test_fullMapResponse(t *testing.T) { }, } - peer1 := types.Machine{ + peer1 := &types.Machine{ ID: 1, MachineKey: "mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507", NodeKey: "nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", @@ -295,7 +295,7 @@ func Test_fullMapResponse(t *testing.T) { }, } - peer2 := types.Machine{ + peer2 := &types.Machine{ ID: 2, MachineKey: "mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507", NodeKey: "nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", @@ -341,7 +341,7 @@ func Test_fullMapResponse(t *testing.T) { name: "no-pol-no-peers-map-response", pol: &policy.ACLPolicy{}, machine: mini, - peers: []types.Machine{}, + peers: types.Machines{}, baseDomain: "", dnsConfig: &tailcfg.DNSConfig{}, derpMap: &tailcfg.DERPMap{}, @@ -369,7 +369,7 @@ func Test_fullMapResponse(t *testing.T) { name: "no-pol-with-peer-map-response", pol: &policy.ACLPolicy{}, machine: mini, - peers: []types.Machine{ + peers: types.Machines{ peer1, }, baseDomain: "", @@ -410,7 +410,7 @@ func Test_fullMapResponse(t *testing.T) { }, }, machine: mini, - peers: []types.Machine{ + peers: types.Machines{ peer1, peer2, }, diff --git a/hscontrol/mapper/tail.go b/hscontrol/mapper/tail.go index 92bd5c9..250b26f 100644 --- a/hscontrol/mapper/tail.go +++ b/hscontrol/mapper/tail.go @@ -41,7 +41,7 @@ func tailNodes( // tailNode converts a Machine into a Tailscale Node. includeRoutes is false for shared nodes // as per the expected behaviour in the official SaaS. func tailNode( - machine types.Machine, + machine *types.Machine, pol *policy.ACLPolicy, dnsConfig *tailcfg.DNSConfig, baseDomain string, diff --git a/hscontrol/mapper/tail_test.go b/hscontrol/mapper/tail_test.go index 9874a77..28bc8e6 100644 --- a/hscontrol/mapper/tail_test.go +++ b/hscontrol/mapper/tail_test.go @@ -45,7 +45,7 @@ func TestTailNode(t *testing.T) { tests := []struct { name string - machine types.Machine + machine *types.Machine pol *policy.ACLPolicy dnsConfig *tailcfg.DNSConfig baseDomain string @@ -54,7 +54,7 @@ func TestTailNode(t *testing.T) { }{ { name: "empty-machine", - machine: types.Machine{}, + machine: &types.Machine{}, pol: &policy.ACLPolicy{}, dnsConfig: &tailcfg.DNSConfig{}, baseDomain: "", @@ -63,7 +63,7 @@ func TestTailNode(t *testing.T) { }, { name: "minimal-machine", - machine: types.Machine{ + machine: &types.Machine{ ID: 0, MachineKey: "mkey:f08305b4ee4250b95a70f3b7504d048d75d899993c624a26d422c67af0422507", NodeKey: "nodekey:9b2ffa7e08cc421a3d2cca9012280f6a236fd0de0b4ce005b30a98ad930306fe", diff --git a/hscontrol/policy/acls.go b/hscontrol/policy/acls.go index d4e2494..90befd5 100644 --- a/hscontrol/policy/acls.go +++ b/hscontrol/policy/acls.go @@ -157,7 +157,7 @@ func (pol *ACLPolicy) generateFilterRules( peers types.Machines, ) ([]tailcfg.FilterRule, error) { rules := []tailcfg.FilterRule{} - machines := append(peers, *machine) + machines := append(peers, machine) for index, acl := range pol.ACLs { if acl.Action != "accept" { @@ -293,7 +293,7 @@ func (pol *ACLPolicy) generateSSHRules( for index, sshACL := range pol.SSHs { var dest netipx.IPSetBuilder for _, src := range sshACL.Destinations { - expanded, err := pol.ExpandAlias(append(peers, *machine), src) + expanded, err := pol.ExpandAlias(append(peers, machine), src) if err != nil { return nil, err } @@ -875,7 +875,7 @@ func isTag(str string) bool { // Invalid tags are tags added by a user on a node, and that user doesn't have authority to add this tag. // Valid tags are tags added by a user that is allowed in the ACL policy to add this tag. func (pol *ACLPolicy) TagsOfMachine( - machine types.Machine, + machine *types.Machine, ) ([]string, []string) { validTags := make([]string, 0) invalidTags := make([]string, 0) @@ -935,7 +935,7 @@ func FilterMachinesByACL( continue } - if machine.CanAccess(filter, &machines[index]) || peer.CanAccess(filter, machine) { + if machine.CanAccess(filter, machines[index]) || peer.CanAccess(filter, machine) { result = append(result, peer) } } diff --git a/hscontrol/policy/acls_test.go b/hscontrol/policy/acls_test.go index b148b37..9afb58a 100644 --- a/hscontrol/policy/acls_test.go +++ b/hscontrol/policy/acls_test.go @@ -394,7 +394,7 @@ acls: netip.MustParseAddr("100.100.100.100"), }, }, types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("200.200.200.200"), }, @@ -909,38 +909,38 @@ func Test_listMachinesInUser(t *testing.T) { name: "1 machine in user", args: args{ machines: types.Machines{ - types.Machine{User: types.User{Name: "joe"}}, + &types.Machine{User: types.User{Name: "joe"}}, }, user: "joe", }, want: types.Machines{ - types.Machine{User: types.User{Name: "joe"}}, + &types.Machine{User: types.User{Name: "joe"}}, }, }, { name: "3 machines, 2 in user", args: args{ machines: types.Machines{ - types.Machine{ID: 1, User: types.User{Name: "joe"}}, - types.Machine{ID: 2, User: types.User{Name: "marc"}}, - types.Machine{ID: 3, User: types.User{Name: "marc"}}, + &types.Machine{ID: 1, User: types.User{Name: "joe"}}, + &types.Machine{ID: 2, User: types.User{Name: "marc"}}, + &types.Machine{ID: 3, User: types.User{Name: "marc"}}, }, user: "marc", }, want: types.Machines{ - types.Machine{ID: 2, User: types.User{Name: "marc"}}, - types.Machine{ID: 3, User: types.User{Name: "marc"}}, + &types.Machine{ID: 2, User: types.User{Name: "marc"}}, + &types.Machine{ID: 3, User: types.User{Name: "marc"}}, }, }, { name: "5 machines, 0 in user", args: args{ machines: types.Machines{ - types.Machine{ID: 1, User: types.User{Name: "joe"}}, - types.Machine{ID: 2, User: types.User{Name: "marc"}}, - types.Machine{ID: 3, User: types.User{Name: "marc"}}, - types.Machine{ID: 4, User: types.User{Name: "marc"}}, - types.Machine{ID: 5, User: types.User{Name: "marc"}}, + &types.Machine{ID: 1, User: types.User{Name: "joe"}}, + &types.Machine{ID: 2, User: types.User{Name: "marc"}}, + &types.Machine{ID: 3, User: types.User{Name: "marc"}}, + &types.Machine{ID: 4, User: types.User{Name: "marc"}}, + &types.Machine{ID: 5, User: types.User{Name: "marc"}}, }, user: "mickael", }, @@ -998,10 +998,10 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "*", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.1")}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.78.84.227"), }, @@ -1024,25 +1024,25 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:accountant", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1065,25 +1065,25 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:hr", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1130,7 +1130,7 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "10.0.0.1", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("10.0.0.1"), }, @@ -1151,7 +1151,7 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "10.0.0.1", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("10.0.0.1"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), @@ -1173,7 +1173,7 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "fd7a:115c:a1e0:ab12:4843:2222:6273:2222", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("10.0.0.1"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), @@ -1242,7 +1242,7 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:hr-webserver", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1253,7 +1253,7 @@ func Test_expandAlias(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1264,13 +1264,13 @@ func Test_expandAlias(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1296,25 +1296,25 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:hr-webserver", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1333,27 +1333,27 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:hr-webserver", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, ForcedTags: []string{"tag:hr-webserver"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "joe"}, ForcedTags: []string{"tag:hr-webserver"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1376,14 +1376,14 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:hr-webserver", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, ForcedTags: []string{"tag:hr-webserver"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1394,13 +1394,13 @@ func Test_expandAlias(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1421,7 +1421,7 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "joe", machines: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1432,7 +1432,7 @@ func Test_expandAlias(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1443,13 +1443,13 @@ func Test_expandAlias(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1498,7 +1498,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1509,7 +1509,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1520,7 +1520,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1530,7 +1530,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { user: "joe", }, want: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.4")}, User: types.User{Name: "joe"}, }, @@ -1548,7 +1548,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { }, }, nodes: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1559,7 +1559,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1570,7 +1570,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1580,7 +1580,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { user: "joe", }, want: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.4")}, User: types.User{Name: "joe"}, }, @@ -1593,7 +1593,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1604,14 +1604,14 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:accountant-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "joe"}, ForcedTags: []string{"tag:accountant-webserver"}, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1621,7 +1621,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { user: "joe", }, want: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.4")}, User: types.User{Name: "joe"}, }, @@ -1634,7 +1634,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1645,7 +1645,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1656,7 +1656,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1666,7 +1666,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { user: "joe", }, want: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, @@ -1677,7 +1677,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, @@ -1688,7 +1688,7 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { RequestTags: []string{"tag:hr-webserver"}, }, }, - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.4"), }, @@ -1716,7 +1716,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { pol ACLPolicy } type args struct { - machine types.Machine + machine *types.Machine peers types.Machines } tests := []struct { @@ -1747,7 +1747,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { }, }, args: args{ - machine: types.Machine{ + machine: &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"), @@ -1792,7 +1792,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { }, }, args: args{ - machine: types.Machine{ + machine: &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"), @@ -1800,7 +1800,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { User: types.User{Name: "mickael"}, }, peers: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), @@ -1839,7 +1839,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { got, err := tt.field.pol.generateFilterRules( - &tt.args.machine, + tt.args.machine, tt.args.peers, ) if (err != nil) != tt.wantErr { @@ -1859,7 +1859,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) { func TestReduceFilterRules(t *testing.T) { tests := []struct { name string - machine types.Machine + machine *types.Machine peers types.Machines pol ACLPolicy want []tailcfg.FilterRule @@ -1875,7 +1875,7 @@ func TestReduceFilterRules(t *testing.T) { }, }, }, - machine: types.Machine{ + machine: &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"), @@ -1883,7 +1883,7 @@ func TestReduceFilterRules(t *testing.T) { User: types.User{Name: "mickael"}, }, peers: types.Machines{ - types.Machine{ + &types.Machine{ IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"), @@ -1898,11 +1898,11 @@ func TestReduceFilterRules(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { rules, _ := tt.pol.generateFilterRules( - &tt.machine, + tt.machine, tt.peers, ) - got := ReduceFilterRules(&tt.machine, rules) + got := ReduceFilterRules(tt.machine, rules) if diff := cmp.Diff(tt.want, got); diff != "" { log.Trace().Interface("got", got).Msg("result") @@ -1915,7 +1915,7 @@ func TestReduceFilterRules(t *testing.T) { func Test_getTags(t *testing.T) { type args struct { aclPolicy *ACLPolicy - machine types.Machine + machine *types.Machine } tests := []struct { name string @@ -1931,7 +1931,7 @@ func Test_getTags(t *testing.T) { "tag:valid": []string{"joe"}, }, }, - machine: types.Machine{ + machine: &types.Machine{ User: types.User{ Name: "joe", }, @@ -1951,7 +1951,7 @@ func Test_getTags(t *testing.T) { "tag:valid": []string{"joe"}, }, }, - machine: types.Machine{ + machine: &types.Machine{ User: types.User{ Name: "joe", }, @@ -1971,7 +1971,7 @@ func Test_getTags(t *testing.T) { "tag:valid": []string{"joe"}, }, }, - machine: types.Machine{ + machine: &types.Machine{ User: types.User{ Name: "joe", }, @@ -1995,7 +1995,7 @@ func Test_getTags(t *testing.T) { "tag:valid": []string{"joe"}, }, }, - machine: types.Machine{ + machine: &types.Machine{ User: types.User{ Name: "joe", }, @@ -2011,7 +2011,7 @@ func Test_getTags(t *testing.T) { name: "empty ACLPolicy should return empty tags and should not panic", args: args{ aclPolicy: &ACLPolicy{}, - machine: types.Machine{ + machine: &types.Machine{ User: types.User{ Name: "joe", }, @@ -2074,21 +2074,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "all hosts can talk to each other", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2111,12 +2111,12 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.2")}, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.3")}, User: types.User{Name: "mickael"}, @@ -2127,21 +2127,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "One host can talk to another, but not all hosts", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2164,7 +2164,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.2")}, User: types.User{Name: "marc"}, @@ -2175,21 +2175,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "host cannot directly talk to destination, but return path is authorized", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2212,7 +2212,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.3")}, User: types.User{Name: "mickael"}, @@ -2223,21 +2223,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "rules allows all hosts to reach one destination", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2262,7 +2262,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), @@ -2275,21 +2275,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "rules allows all hosts to reach one destination, destination can reach all hosts", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2314,14 +2314,14 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2334,21 +2334,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "rule allows all hosts to reach all destinations", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2371,14 +2371,14 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.3")}, User: types.User{Name: "mickael"}, @@ -2389,21 +2389,21 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "without rule all communications are forbidden", args: args{ machines: types.Machines{ // list of all machines in the database - types.Machine{ + &types.Machine{ ID: 1, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.1"), }, User: types.User{Name: "joe"}, }, - types.Machine{ + &types.Machine{ ID: 2, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.2"), }, User: types.User{Name: "marc"}, }, - types.Machine{ + &types.Machine{ ID: 3, IPAddresses: types.MachineAddresses{ netip.MustParseAddr("100.64.0.3"), @@ -2429,7 +2429,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { name: "issue-699-broken-star", args: args{ machines: types.Machines{ // - types.Machine{ + &types.Machine{ ID: 1, Hostname: "ts-head-upcrmb", IPAddresses: types.MachineAddresses{ @@ -2438,7 +2438,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, User: types.User{Name: "user1"}, }, - types.Machine{ + &types.Machine{ ID: 2, Hostname: "ts-unstable-rlwpvr", IPAddresses: types.MachineAddresses{ @@ -2447,7 +2447,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, User: types.User{Name: "user1"}, }, - types.Machine{ + &types.Machine{ ID: 3, Hostname: "ts-head-8w6paa", IPAddresses: types.MachineAddresses{ @@ -2456,7 +2456,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, User: types.User{Name: "user2"}, }, - types.Machine{ + &types.Machine{ ID: 4, Hostname: "ts-unstable-lys2ib", IPAddresses: types.MachineAddresses{ @@ -2491,7 +2491,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, want: types.Machines{ - types.Machine{ + &types.Machine{ ID: 1, Hostname: "ts-head-upcrmb", IPAddresses: types.MachineAddresses{ @@ -2500,7 +2500,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, User: types.User{Name: "user1"}, }, - types.Machine{ + &types.Machine{ ID: 2, Hostname: "ts-unstable-rlwpvr", IPAddresses: types.MachineAddresses{ @@ -2514,7 +2514,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { { name: "failing-edge-case-during-p3-refactor", args: args{ - machines: []types.Machine{ + machines: []*types.Machine{ { ID: 1, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")}, @@ -2544,7 +2544,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { User: types.User{Name: "mini"}, }, }, - want: []types.Machine{ + want: []*types.Machine{ { ID: 2, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.3")}, @@ -2556,7 +2556,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { { name: "p4-host-in-netmap-user2-dest-bug", args: args{ - machines: []types.Machine{ + machines: []*types.Machine{ { ID: 1, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")}, @@ -2613,7 +2613,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { User: types.User{Name: "user2"}, }, }, - want: []types.Machine{ + want: []*types.Machine{ { ID: 1, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")}, @@ -2637,7 +2637,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { { name: "p4-host-in-netmap-user1-dest-bug", args: args{ - machines: []types.Machine{ + machines: []*types.Machine{ { ID: 1, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")}, @@ -2694,7 +2694,7 @@ func Test_getFilteredByACLPeers(t *testing.T) { User: types.User{Name: "user1"}, }, }, - want: []types.Machine{ + want: []*types.Machine{ { ID: 1, IPAddresses: []netip.Addr{netip.MustParseAddr("100.64.0.2")}, @@ -2749,7 +2749,7 @@ func TestSSHRules(t *testing.T) { }, }, peers: types.Machines{ - types.Machine{ + &types.Machine{ Hostname: "testmachine2", IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.1")}, UserID: 0, @@ -2857,7 +2857,7 @@ func TestSSHRules(t *testing.T) { }, }, peers: types.Machines{ - types.Machine{ + &types.Machine{ Hostname: "testmachine2", IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.99.42")}, UserID: 0, @@ -2984,7 +2984,7 @@ func TestValidExpandTagOwnersInSources(t *testing.T) { RequestTags: []string{"tag:test"}, } - machine := types.Machine{ + machine := &types.Machine{ ID: 0, MachineKey: "foo", NodeKey: "bar", @@ -3011,7 +3011,7 @@ func TestValidExpandTagOwnersInSources(t *testing.T) { }, } - got, _, err := GenerateFilterAndSSHRules(pol, &machine, types.Machines{}) + got, _, err := GenerateFilterAndSSHRules(pol, machine, types.Machines{}) assert.NoError(t, err) want := []tailcfg.FilterRule{ @@ -3039,7 +3039,7 @@ func TestInvalidTagValidUser(t *testing.T) { RequestTags: []string{"tag:foo"}, } - machine := types.Machine{ + machine := &types.Machine{ ID: 1, MachineKey: "12345", NodeKey: "bar", @@ -3065,7 +3065,7 @@ func TestInvalidTagValidUser(t *testing.T) { }, } - got, _, err := GenerateFilterAndSSHRules(pol, &machine, types.Machines{}) + got, _, err := GenerateFilterAndSSHRules(pol, machine, types.Machines{}) assert.NoError(t, err) want := []tailcfg.FilterRule{ @@ -3093,7 +3093,7 @@ func TestValidExpandTagOwnersInDestinations(t *testing.T) { RequestTags: []string{"tag:test"}, } - machine := types.Machine{ + machine := &types.Machine{ ID: 1, MachineKey: "12345", NodeKey: "bar", @@ -3127,7 +3127,7 @@ func TestValidExpandTagOwnersInDestinations(t *testing.T) { // c.Assert(rules[0].DstPorts, check.HasLen, 1) // c.Assert(rules[0].DstPorts[0].IP, check.Equals, "100.64.0.1/32") - got, _, err := GenerateFilterAndSSHRules(pol, &machine, types.Machines{}) + got, _, err := GenerateFilterAndSSHRules(pol, machine, types.Machines{}) assert.NoError(t, err) want := []tailcfg.FilterRule{ @@ -3157,7 +3157,7 @@ func TestValidTagInvalidUser(t *testing.T) { RequestTags: []string{"tag:webapp"}, } - machine := types.Machine{ + machine := &types.Machine{ ID: 1, MachineKey: "12345", NodeKey: "bar", @@ -3177,7 +3177,7 @@ func TestValidTagInvalidUser(t *testing.T) { Hostname: "Hostname", } - machine2 := types.Machine{ + machine2 := &types.Machine{ ID: 2, MachineKey: "56789", NodeKey: "bar2", @@ -3203,7 +3203,7 @@ func TestValidTagInvalidUser(t *testing.T) { }, } - got, _, err := GenerateFilterAndSSHRules(pol, &machine, types.Machines{machine2}) + got, _, err := GenerateFilterAndSSHRules(pol, machine, types.Machines{machine2}) assert.NoError(t, err) want := []tailcfg.FilterRule{ diff --git a/hscontrol/poll.go b/hscontrol/poll.go index c6b18bd..b96f142 100644 --- a/hscontrol/poll.go +++ b/hscontrol/poll.go @@ -80,9 +80,21 @@ func (h *Headscale) handlePoll( logInfo, logErr := logPollFunc(mapRequest, machine, isNoise) + // When a node connects to control, list the peers it has at + // that given point, further updates are kept in memory in + // the Mapper, which lives for the duration of the polling + // session. + peers, err := h.db.ListPeers(machine) + if err != nil { + logErr(err, "Failed to list peers when opening poller") + http.Error(writer, "", http.StatusInternalServerError) + + return + } + mapp := mapper.NewMapper( machine, - h.db, + peers, h.privateKey2019, isNoise, h.DERPMap, @@ -97,7 +109,7 @@ func (h *Headscale) handlePoll( machine.DiscoKey = util.DiscoPublicKeyStripPrefix(mapRequest.DiscoKey) now := time.Now().UTC() - err := h.db.ProcessMachineRoutes(machine) + err = h.db.SaveMachineRoutes(machine) if err != nil { logErr(err, "Error processing machine routes") } @@ -142,7 +154,7 @@ func (h *Headscale) handlePoll( h.nodeNotifier.NotifyWithIgnore( types.StateUpdate{ Type: types.StatePeerChanged, - Changed: []uint64{machine.ID}, + Changed: types.Machines{machine}, }, machine.MachineKey) } diff --git a/hscontrol/types/common.go b/hscontrol/types/common.go index 3a00104..e80ef8f 100644 --- a/hscontrol/types/common.go +++ b/hscontrol/types/common.go @@ -124,7 +124,7 @@ type StateUpdate struct { // Changed must be set when Type is StatePeerChanged and // contain the Machine IDs of machines that has changed. - Changed []uint64 + Changed Machines // Removed must be set when Type is StatePeerRemoved and // contain a list of the nodes that has been removed from diff --git a/hscontrol/types/machine.go b/hscontrol/types/machine.go index 0452286..9a86902 100644 --- a/hscontrol/types/machine.go +++ b/hscontrol/types/machine.go @@ -68,8 +68,7 @@ type Machine struct { } type ( - Machines []Machine - MachinesP []*Machine + Machines []*Machine ) type MachineAddresses []netip.Addr @@ -343,19 +342,8 @@ func (machines Machines) String() string { return fmt.Sprintf("[ %s ](%d)", strings.Join(temp, ", "), len(temp)) } -// TODO(kradalby): Remove when we have generics... -func (machines MachinesP) String() string { - temp := make([]string, len(machines)) - - for index, machine := range machines { - temp[index] = machine.Hostname - } - - return fmt.Sprintf("[ %s ](%d)", strings.Join(temp, ", "), len(temp)) -} - -func (machines Machines) IDMap() map[uint64]Machine { - ret := map[uint64]Machine{} +func (machines Machines) IDMap() map[uint64]*Machine { + ret := map[uint64]*Machine{} for _, machine := range machines { ret[machine.ID] = machine