From 9b7d657cbe4ae7f648798a7080819f3863f6b7c8 Mon Sep 17 00:00:00 2001 From: Jamie Greeff Date: Wed, 29 Dec 2021 09:58:10 +0000 Subject: [PATCH 01/38] Return all peers instead of peers in same namespace --- dns.go | 6 +++- machine.go | 87 ++++++++++++++++++++++++++++++++++++++---------------- 2 files changed, 67 insertions(+), 26 deletions(-) diff --git a/dns.go b/dns.go index 8ecd993c..37daa884 100644 --- a/dns.go +++ b/dns.go @@ -163,7 +163,11 @@ func getMapResponseDNSConfig( dnsConfig = dnsConfigOrig.Clone() dnsConfig.Domains = append( dnsConfig.Domains, - fmt.Sprintf("%s.%s", machine.Namespace.Name, baseDomain), + fmt.Sprintf( + "%s.%s", + strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + baseDomain, + ), ) namespaceSet := set.New(set.ThreadSafe) diff --git a/machine.go b/machine.go index 2b462985..aef310c5 100644 --- a/machine.go +++ b/machine.go @@ -119,6 +119,33 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } +// Our Pineapple fork of Headscale ignores namespaces when dealing with peers +// and instead passes ALL peers across all namespaces to each client. Access between clients +// is then enforced with ACL policies. +func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msg("Finding all peers") + + machines := Machines{} + if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", + machine.MachineKey).Find(&machines).Error; err != nil { + log.Error().Err(err).Msg("Error accessing db") + + return Machines{}, err + } + + sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID }) + + log.Trace(). + Caller(). + Str("machine", machine.Name). + Msgf("Found all machines: %s", machines.String()) + + return machines, nil +} + func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). @@ -206,7 +233,40 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { } func (h *Headscale) getPeers(machine *Machine) (Machines, error) { - direct, err := h.getDirectPeers(machine) + // direct, err := h.getDirectPeers(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // shared, err := h.getShared(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // sharedTo, err := h.getSharedTo(machine) + // if err != nil { + // log.Error(). + // Caller(). + // Err(err). + // Msg("Cannot fetch peers") + + // return Machines{}, err + // } + + // peers := append(direct, shared...) + // peers = append(peers, sharedTo...) + + peers, err := h.getAllPeers(machine) if err != nil { log.Error(). Caller(). @@ -216,29 +276,6 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { return Machines{}, err } - shared, err := h.getShared(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - - sharedTo, err := h.getSharedTo(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err - } - - peers := append(direct, shared...) - peers = append(peers, sharedTo...) - sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) log.Trace(). @@ -597,7 +634,7 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - machine.Namespace.Name, + strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine baseDomain, ) } else { From e482dfeed4a06e7d9be966a8068dd06b826f686d Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Thu, 3 Feb 2022 19:53:11 +0100 Subject: [PATCH 02/38] feat(machine): add ACLFilter if ACL's are enabled. This commit change the default behaviour and remove the notion of namespaces between the hosts. It allows all namespaces to be only filtered by the ACLs. This behavior is closer to tailsnet. --- machine.go | 133 ++++++++++++++++++++++++++++++++---------------- machine_test.go | 84 ++++++++++++++++++++++++++++++ utils.go | 9 ++++ 3 files changed, 183 insertions(+), 43 deletions(-) diff --git a/machine.go b/machine.go index aef310c5..231c179d 100644 --- a/machine.go +++ b/machine.go @@ -119,14 +119,21 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } -// Our Pineapple fork of Headscale ignores namespaces when dealing with peers -// and instead passes ALL peers across all namespaces to each client. Access between clients -// is then enforced with ACL policies. -func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { +func containsAddresses(inputs []string, addrs MachineAddresses) bool { + for _, addr := range addrs.ToStringSlice() { + if containsString(inputs, addr) { + return true + } + } + return false +} + +// getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. +func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). - Msg("Finding all peers") + Msg("Finding peers filtered by ACLs") machines := Machines{} if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", @@ -135,15 +142,50 @@ func (h *Headscale) getAllPeers(machine *Machine) (Machines, error) { return Machines{}, err } + mMachines := make(map[uint64]Machine) - sort.Slice(machines, func(i, j int) bool { return machines[i].ID < machines[j].ID }) + // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules + // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. + + // FIXME: On official control plane if a rule allow user A to talk to user B but NO rule allows user B to talk to + // user A. The behaviour is the following + // + // On official tailscale control plane: + // on first `tailscale status`` on node A we can see node B. The `tailscale status` command on node B doesn't show node A + // We can successfully establish a communication from A to B. When it's done, if we run the `tailscale status` command + // on node B again we can now see node A. It's not possible to establish a communication from node B to node A. + // On this implementation of the feature + // on any `tailscale status` command on node A we can see node B. The `tailscale status` command on node B DOES show A. + // + // I couldn't find a way to not clutter the output of `tailscale status` with all nodes that we could be talking to. + // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know + // how to talk to node A and then add the peering resource. + + for _, m := range machines { + for _, rule := range h.aclRules { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, m.IPAddresses) || containsString(dst, "*"))) || + (containsAddresses(rule.SrcIPs, m.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + mMachines[m.ID] = m + } + } + } + + var authorizedMachines Machines + for _, m := range mMachines { + authorizedMachines = append(authorizedMachines, m) + } + sort.Slice(authorizedMachines, func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }) log.Trace(). Caller(). Str("machine", machine.Name). - Msgf("Found all machines: %s", machines.String()) + Msgf("Found some machines: %s", machines.String()) - return machines, nil + return authorizedMachines, nil } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { @@ -233,47 +275,52 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { } func (h *Headscale) getPeers(machine *Machine) (Machines, error) { - // direct, err := h.getDirectPeers(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + var peers Machines + var err error + // If ACLs rules are defined, filter visible host list with the ACLs + // else use the classic namespace scope + if h.aclPolicy != nil { + peers, err = h.getFilteredByACLPeers(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // return Machines{}, err - // } + return Machines{}, err + } + } else { + direct, err := h.getDirectPeers(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // shared, err := h.getShared(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + return Machines{}, err + } - // return Machines{}, err - // } + shared, err := h.getShared(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // sharedTo, err := h.getSharedTo(machine) - // if err != nil { - // log.Error(). - // Caller(). - // Err(err). - // Msg("Cannot fetch peers") + return Machines{}, err + } - // return Machines{}, err - // } + sharedTo, err := h.getSharedTo(machine) + if err != nil { + log.Error(). + Caller(). + Err(err). + Msg("Cannot fetch peers") - // peers := append(direct, shared...) - // peers = append(peers, sharedTo...) - - peers, err := h.getAllPeers(machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") - - return Machines{}, err + return Machines{}, err + } + peers = append(direct, shared...) + peers = append(peers, sharedTo...) } sort.Slice(peers, func(i, j int) bool { return peers[i].ID < peers[j].ID }) diff --git a/machine_test.go b/machine_test.go index ff1dc914..f84603a4 100644 --- a/machine_test.go +++ b/machine_test.go @@ -1,6 +1,7 @@ package headscale import ( + "fmt" "strconv" "time" @@ -154,6 +155,89 @@ func (s *Suite) TestGetDirectPeers(c *check.C) { c.Assert(peersOfMachine0[8].Name, check.Equals, "testmachine10") } +func (s *Suite) TestGetACLFilteredPeers(c *check.C) { + type base struct { + namespace *Namespace + key *PreAuthKey + } + + var stor []base + + for _, name := range []string{"test", "admin"} { + namespace, err := app.CreateNamespace(name) + c.Assert(err, check.IsNil) + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + stor = append(stor, base{namespace, pak}) + + } + + _, err := app.GetMachineByID(0) + c.Assert(err, check.NotNil) + + for index := 0; index <= 10; index++ { + machine := Machine{ + ID: uint64(index), + MachineKey: "foo" + strconv.Itoa(index), + NodeKey: "bar" + strconv.Itoa(index), + DiscoKey: "faa" + strconv.Itoa(index), + IPAddress: fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)), + Name: "testmachine" + strconv.Itoa(index), + NamespaceID: stor[index%2].namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(stor[index%2].key.ID), + } + app.db.Save(&machine) + } + + app.aclPolicy = &ACLPolicy{ + Groups: map[string][]string{ + "group:test": {"admin"}, + }, + Hosts: map[string]netaddr.IPPrefix{}, + TagOwners: map[string][]string{}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"admin"}, Ports: []string{"*:*"}}, + {Action: "accept", Users: []string{"test"}, Ports: []string{"test:*"}}, + }, + Tests: []ACLTest{}, + } + + rules, err := app.generateACLRules() + c.Assert(err, check.IsNil) + app.aclRules = rules + + adminMachine, err := app.GetMachineByID(1) + c.Logf("Machine(%v), namespace: %v", adminMachine.Name, adminMachine.Namespace) + c.Assert(err, check.IsNil) + + testMachine, err := app.GetMachineByID(2) + c.Logf("Machine(%v), namespace: %v", testMachine.Name, testMachine.Namespace) + c.Assert(err, check.IsNil) + + _, err = testMachine.GetHostInfo() + c.Assert(err, check.IsNil) + + peersOfTestMachine, err := app.getFilteredByACLPeers(testMachine) + c.Assert(err, check.IsNil) + + peersOfAdminMachine, err := app.getFilteredByACLPeers(adminMachine) + c.Assert(err, check.IsNil) + + c.Log(peersOfTestMachine) + c.Assert(len(peersOfTestMachine), check.Equals, 4) + c.Assert(peersOfTestMachine[0].Name, check.Equals, "testmachine4") + c.Assert(peersOfTestMachine[1].Name, check.Equals, "testmachine6") + c.Assert(peersOfTestMachine[3].Name, check.Equals, "testmachine10") + + c.Log(peersOfAdminMachine) + c.Assert(len(peersOfAdminMachine), check.Equals, 9) + c.Assert(peersOfAdminMachine[0].Name, check.Equals, "testmachine2") + c.Assert(peersOfAdminMachine[2].Name, check.Equals, "testmachine4") + c.Assert(peersOfAdminMachine[5].Name, check.Equals, "testmachine7") +} + func (s *Suite) TestExpireMachine(c *check.C) { namespace, err := app.CreateNamespace("test") c.Assert(err, check.IsNil) diff --git a/utils.go b/utils.go index a6be8cc4..794971a1 100644 --- a/utils.go +++ b/utils.go @@ -212,6 +212,15 @@ func (h *Headscale) getUsedIPs() ([]netaddr.IP, error) { return ips, nil } +func containsString(ss []string, s string) bool { + for _, v := range ss { + if v == s { + return true + } + } + return false +} + func containsIPs(ips []netaddr.IP, ip netaddr.IP) bool { for _, v := range ips { if v == ip { From e9949b4c70e5a0bc0599e10d854ece73976c06e4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Thu, 3 Feb 2022 20:00:41 +0100 Subject: [PATCH 03/38] feat(acls): simplify updating rules --- acls.go | 8 +++++--- machine_test.go | 3 +-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/acls.go b/acls.go index 326625b9..e2b2a27c 100644 --- a/acls.go +++ b/acls.go @@ -69,14 +69,16 @@ func (h *Headscale) LoadACLPolicy(path string) error { } h.aclPolicy = &policy + return h.UpdateACLRules() +} + +func (h *Headscale) UpdateACLRules() error { rules, err := h.generateACLRules() if err != nil { return err } - h.aclRules = rules - log.Trace().Interface("ACL", rules).Msg("ACL rules generated") - + h.aclRules = rules return nil } diff --git a/machine_test.go b/machine_test.go index f84603a4..56fdf1f3 100644 --- a/machine_test.go +++ b/machine_test.go @@ -204,9 +204,8 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { Tests: []ACLTest{}, } - rules, err := app.generateACLRules() + err = app.UpdateACLRules() c.Assert(err, check.IsNil) - app.aclRules = rules adminMachine, err := app.GetMachineByID(1) c.Logf("Machine(%v), namespace: %v", adminMachine.Name, adminMachine.Namespace) From fb45138fc19fffeb336e46c0a859ee9c711240be Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Sat, 5 Feb 2022 17:18:39 +0100 Subject: [PATCH 04/38] feat(acls): check acl owners and add bunch of tests --- acls.go | 96 ++++++++++++++------- acls_test.go | 220 ++++++++++++++++++++++++++++++++++++++++++++++++ machine_test.go | 2 +- 3 files changed, 287 insertions(+), 31 deletions(-) diff --git a/acls.go b/acls.go index e2b2a27c..c86e315f 100644 --- a/acls.go +++ b/acls.go @@ -2,6 +2,7 @@ package headscale import ( "encoding/json" + "errors" "fmt" "io" "os" @@ -90,8 +91,6 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return nil, errInvalidAction } - filterRule := tailcfg.FilterRule{} - srcIPs := []string{} for innerIndex, user := range acl.Users { srcs, err := h.generateACLPolicySrcIP(user) @@ -103,7 +102,6 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { } srcIPs = append(srcIPs, srcs...) } - filterRule.SrcIPs = srcIPs destPorts := []tailcfg.NetPortRange{} for innerIndex, ports := range acl.Ports { @@ -174,17 +172,23 @@ func (h *Headscale) generateACLPolicyDestPorts( return dests, nil } +// expandalias has an input of either +// - a namespace +// - a group +// - a tag +// and transform these in IPAddresses func (h *Headscale) expandAlias(alias string) ([]string, error) { if alias == "*" { return []string{"*"}, nil } if strings.HasPrefix(alias, "group:") { - if _, ok := h.aclPolicy.Groups[alias]; !ok { - return nil, errInvalidGroup + namespaces, err := h.expandGroup(alias) + if err != nil { + return nil, err } ips := []string{} - for _, n := range h.aclPolicy.Groups[alias] { + for _, n := range namespaces { nodes, err := h.ListMachinesInNamespace(n) if err != nil { return nil, errInvalidNamespace @@ -198,40 +202,35 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { } if strings.HasPrefix(alias, "tag:") { - if _, ok := h.aclPolicy.TagOwners[alias]; !ok { - return nil, errInvalidTag - } - - // This will have HORRIBLE performance. - // We need to change the data model to better store tags - machines := []Machine{} - if err := h.db.Where("registered").Find(&machines).Error; err != nil { + var ips []string + owners, err := h.expandTagOwners(alias) + if err != nil { return nil, err } - ips := []string{} - for _, machine := range machines { - hostinfo := tailcfg.Hostinfo{} - if len(machine.HostInfo) != 0 { - hi, err := machine.HostInfo.MarshalJSON() + for _, namespace := range owners { + machines, err := h.ListMachinesInNamespace(namespace) + if err != nil { + if errors.Is(err, errNamespaceNotFound) { + continue + } else { + return nil, err + } + } + for _, machine := range machines { + if len(machine.HostInfo) == 0 { + continue + } + hi, err := machine.GetHostInfo() if err != nil { return nil, err } - err = json.Unmarshal(hi, &hostinfo) - if err != nil { - return nil, err - } - - // FIXME: Check TagOwners allows this - for _, t := range hostinfo.RequestTags { - if alias[4:] == t { + for _, t := range hi.RequestTags { + if alias == t { ips = append(ips, machine.IPAddresses.ToStringSlice()...) - - break } } } } - return ips, nil } @@ -266,6 +265,43 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { return nil, errInvalidUserSection } +// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group +// a group cannot be composed of groups +func (h *Headscale) expandTagOwners(owner string) ([]string, error) { + var owners []string + ows, ok := h.aclPolicy.TagOwners[owner] + if !ok { + return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, owner) + } + for _, ow := range ows { + if strings.HasPrefix(ow, "group:") { + gs, err := h.expandGroup(ow) + if err != nil { + return []string{}, err + } + owners = append(owners, gs...) + } else { + owners = append(owners, ow) + } + } + return owners, nil +} + +// expandGroup will return the list of namespace inside the group +// after some validation +func (h *Headscale) expandGroup(group string) ([]string, error) { + gs, ok := h.aclPolicy.Groups[group] + if !ok { + return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + } + for _, g := range gs { + if strings.HasPrefix(g, "group:") { + return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + } + } + return gs, nil +} + func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { if portsStr == "*" { return &[]tailcfg.PortRange{ diff --git a/acls_test.go b/acls_test.go index c35f4f84..f2fb6a03 100644 --- a/acls_test.go +++ b/acls_test.go @@ -1,7 +1,11 @@ package headscale import ( + "errors" + "gopkg.in/check.v1" + "gorm.io/datatypes" + "inet.af/netaddr" ) func (s *Suite) TestWrongPath(c *check.C) { @@ -52,6 +56,222 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } +func (s *Suite) TestInvalidAction(c *check.C) { + app.aclPolicy = &ACLPolicy{ + ACLs: []ACL{ + {Action: "invalidAction", Users: []string{"*"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidAction), check.Equals, true) +} + +func (s *Suite) TestInvalidGroupInGroup(c *check.C) { + // this ACL is wrong because the group in users sections doesn't exist + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo"}, "group:error": []string{"foo", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"group:error"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidGroup), check.Equals, true) +} + +func (s *Suite) TestInvalidTagOwners(c *check.C) { + // this ACL is wrong because no tagOwners own the requested tag for the server + app.aclPolicy = &ACLPolicy{ + ACLs: []ACL{ + {Action: "accept", Users: []string{"tag:foo"}, Ports: []string{"*:*"}}, + }, + } + err := app.UpdateACLRules() + c.Assert(errors.Is(err, errInvalidTag), check.Equals, true) +} + +// this test should validate that we can expand a group in a TagOWner section and +// match properly the IP's of the related hosts. The owner is valid and the tag is also valid. +// the tag is matched in the Users section +func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + machine := Machine{ + ID: 0, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo", "foobar"}}, + TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"tag:test"}, Ports: []string{"*:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.1") +} + +// this test should validate that we can expand a group in a TagOWner section and +// match properly the IP's of the related hosts. The owner is valid and the tag is also valid. +// the tag is matched in the Ports section +func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + Groups: Groups{"group:test": []string{"foo", "foobar"}}, + TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"*"}, Ports: []string{"tag:test:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].DstPorts, check.HasLen, 1) + c.Assert(app.aclRules[0].DstPorts[0].IP, check.Equals, "100.64.0.1") +} + +// need a test with: +// tag on a host that isn't owned by a tag owners. So the namespace +// of the host should be valid +func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "testmachine") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "testmachine", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"foo"}, Ports: []string{"*:*"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.1") +} + +// tag on a host is owned by a tag owner, the tag is valid. +// an ACL rule is matching the tag to a namespace. It should not be valid since the +// host should be tied to the tag now. +func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { + namespace, err := app.CreateNamespace("foo") + c.Assert(err, check.IsNil) + + pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) + c.Assert(err, check.IsNil) + + _, err = app.GetMachine("foo", "webserver") + c.Assert(err, check.NotNil) + b := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + machine := Machine{ + ID: 1, + MachineKey: "foo", + NodeKey: "bar", + DiscoKey: "faa", + Name: "webserver", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + _, err = app.GetMachine("foo", "user") + b = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") + c.Assert(err, check.NotNil) + machine = Machine{ + ID: 2, + MachineKey: "foo2", + NodeKey: "bar2", + DiscoKey: "faab", + Name: "user", + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + NamespaceID: namespace.ID, + Registered: true, + RegisterMethod: RegisterMethodAuthKey, + AuthKeyID: uint(pak.ID), + HostInfo: datatypes.JSON(b), + } + app.db.Save(&machine) + + app.aclPolicy = &ACLPolicy{ + TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, + ACLs: []ACL{ + {Action: "accept", Users: []string{"foo"}, Ports: []string{"tag:webapp:80,443"}}, + }, + } + err = app.UpdateACLRules() + c.Assert(err, check.IsNil) + c.Logf("Rules: %v", app.aclRules) + c.Assert(app.aclRules, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 0) +} + func (s *Suite) TestPortRange(c *check.C) { err := app.LoadACLPolicy("./tests/acls/acl_policy_basic_range.hujson") c.Assert(err, check.IsNil) diff --git a/machine_test.go b/machine_test.go index 56fdf1f3..203289ac 100644 --- a/machine_test.go +++ b/machine_test.go @@ -181,7 +181,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { MachineKey: "foo" + strconv.Itoa(index), NodeKey: "bar" + strconv.Itoa(index), DiscoKey: "faa" + strconv.Itoa(index), - IPAddress: fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)), + IPAddresses: MachineAddresses{netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)))}, Name: "testmachine" + strconv.Itoa(index), NamespaceID: stor[index%2].namespace.ID, Registered: true, From 97eac3b9389e5eb17dc901f15bdb4882d0e7a167 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Sun, 6 Feb 2022 17:55:12 +0100 Subject: [PATCH 05/38] feat(acl): update frequently the aclRules This call should be done quite at each modification of a server resources like RequestTags. When a server changes it's tag we should rebuild the ACL rules. When a server is added to headscale we also should update the ACLRules. --- poll.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/poll.go b/poll.go index dd3956fb..c2a51d11 100644 --- a/poll.go +++ b/poll.go @@ -91,6 +91,12 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) now := time.Now().UTC() + // update ACLRules with peer informations (to update server tags if necessary) + err = h.UpdateACLRules() + if err != nil { + log.Error().Caller().Str("func", "handleAuthKey").Str("machine", machine.Name).Err(err) + } + // From Tailscale client: // // ReadOnly is whether the client just wants to fetch the MapResponse, From de5994644790b6948d1d39b12a59dfb9931df797 Mon Sep 17 00:00:00 2001 From: Adrien Raffin Date: Mon, 7 Feb 2022 16:12:05 +0100 Subject: [PATCH 06/38] feat(acls): rewrite functions to be testable Rewrite some function to get rid of the dependency on Headscale object. This allows us to write succinct test that are more easy to review and implement. The improvements of the tests allowed to write the removal of the tagged hosts from the namespace as specified here: https://tailscale.com/kb/1068/acl-tags/ --- acls.go | 187 ++++++++++-------- acls_test.go | 521 ++++++++++++++++++++++++++++++++++++++++++++++++++- machine.go | 13 ++ 3 files changed, 646 insertions(+), 75 deletions(-) diff --git a/acls.go b/acls.go index c86e315f..9dd1260d 100644 --- a/acls.go +++ b/acls.go @@ -2,7 +2,6 @@ package headscale import ( "encoding/json" - "errors" "fmt" "io" "os" @@ -86,6 +85,11 @@ func (h *Headscale) UpdateACLRules() error { func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { rules := []tailcfg.FilterRule{} + machines, err := h.ListAllMachines() + if err != nil { + return nil, err + } + for index, acl := range h.aclPolicy.ACLs { if acl.Action != "accept" { return nil, errInvalidAction @@ -93,7 +97,7 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { srcIPs := []string{} for innerIndex, user := range acl.Users { - srcs, err := h.generateACLPolicySrcIP(user) + srcs, err := h.generateACLPolicySrcIP(machines, *h.aclPolicy, user) if err != nil { log.Error(). Msgf("Error parsing ACL %d, User %d", index, innerIndex) @@ -105,7 +109,7 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { destPorts := []tailcfg.NetPortRange{} for innerIndex, ports := range acl.Ports { - dests, err := h.generateACLPolicyDestPorts(ports) + dests, err := h.generateACLPolicyDestPorts(machines, *h.aclPolicy, ports) if err != nil { log.Error(). Msgf("Error parsing ACL %d, Port %d", index, innerIndex) @@ -124,11 +128,13 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return rules, nil } -func (h *Headscale) generateACLPolicySrcIP(u string) ([]string, error) { - return h.expandAlias(u) +func (h *Headscale) generateACLPolicySrcIP(machines []Machine, aclPolicy ACLPolicy, u string) ([]string, error) { + return expandAlias(machines, aclPolicy, u) } func (h *Headscale) generateACLPolicyDestPorts( + machines []Machine, + aclPolicy ACLPolicy, d string, ) ([]tailcfg.NetPortRange, error) { tokens := strings.Split(d, ":") @@ -149,11 +155,11 @@ func (h *Headscale) generateACLPolicyDestPorts( alias = fmt.Sprintf("%s:%s", tokens[0], tokens[1]) } - expanded, err := h.expandAlias(alias) + expanded, err := expandAlias(machines, aclPolicy, alias) if err != nil { return nil, err } - ports, err := h.expandPorts(tokens[len(tokens)-1]) + ports, err := expandPorts(tokens[len(tokens)-1]) if err != nil { return nil, err } @@ -177,52 +183,40 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a group // - a tag // and transform these in IPAddresses -func (h *Headscale) expandAlias(alias string) ([]string, error) { +func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { + ips := []string{} if alias == "*" { return []string{"*"}, nil } if strings.HasPrefix(alias, "group:") { - namespaces, err := h.expandGroup(alias) + namespaces, err := expandGroup(aclPolicy, alias) if err != nil { - return nil, err + return ips, err } - ips := []string{} for _, n := range namespaces { - nodes, err := h.ListMachinesInNamespace(n) - if err != nil { - return nil, errInvalidNamespace - } + nodes := listMachinesInNamespace(machines, n) for _, node := range nodes { ips = append(ips, node.IPAddresses.ToStringSlice()...) } } - return ips, nil } if strings.HasPrefix(alias, "tag:") { - var ips []string - owners, err := h.expandTagOwners(alias) + owners, err := expandTagOwners(aclPolicy, alias) if err != nil { - return nil, err + return ips, err } for _, namespace := range owners { - machines, err := h.ListMachinesInNamespace(namespace) - if err != nil { - if errors.Is(err, errNamespaceNotFound) { - continue - } else { - return nil, err - } - } + machines := listMachinesInNamespace(machines, namespace) for _, machine := range machines { if len(machine.HostInfo) == 0 { continue } hi, err := machine.GetHostInfo() if err != nil { - return nil, err + return ips, err } for _, t := range hi.RequestTags { if alias == t { @@ -234,75 +228,75 @@ func (h *Headscale) expandAlias(alias string) ([]string, error) { return ips, nil } - n, err := h.GetNamespace(alias) - if err == nil { - nodes, err := h.ListMachinesInNamespace(n.Name) - if err != nil { - return nil, err - } - ips := []string{} - for _, n := range nodes { - ips = append(ips, n.IPAddresses.ToStringSlice()...) - } - + // if alias is a namespace + nodes := listMachinesInNamespace(machines, alias) + nodes, err := excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) + if err != nil { + return ips, err + } + for _, n := range nodes { + ips = append(ips, n.IPAddresses.ToStringSlice()...) + } + if len(ips) > 0 { return ips, nil } - if h, ok := h.aclPolicy.Hosts[alias]; ok { + // if alias is an host + if h, ok := aclPolicy.Hosts[alias]; ok { return []string{h.String()}, nil } + // if alias is an IP ip, err := netaddr.ParseIP(alias) if err == nil { return []string{ip.String()}, nil } + // if alias is an CIDR cidr, err := netaddr.ParseIPPrefix(alias) if err == nil { return []string{cidr.String()}, nil } - return nil, errInvalidUserSection + return ips, errInvalidUserSection } -// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group -// a group cannot be composed of groups -func (h *Headscale) expandTagOwners(owner string) ([]string, error) { - var owners []string - ows, ok := h.aclPolicy.TagOwners[owner] - if !ok { - return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, owner) +// excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones +// that are correctly tagged since they should not be listed as being in the namespace +// we assume in this function that we only have nodes from 1 namespace. +func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace string) ([]Machine, error) { + out := []Machine{} + tags := []string{} + for tag, ns := range aclPolicy.TagOwners { + if containsString(ns, namespace) { + tags = append(tags, tag) + } } - for _, ow := range ows { - if strings.HasPrefix(ow, "group:") { - gs, err := h.expandGroup(ow) - if err != nil { - return []string{}, err + // for each machine if tag is in tags list, don't append it. + for _, machine := range nodes { + if len(machine.HostInfo) == 0 { + out = append(out, machine) + continue + } + hi, err := machine.GetHostInfo() + if err != nil { + return out, err + } + found := false + for _, t := range hi.RequestTags { + if containsString(tags, t) { + found = true + break } - owners = append(owners, gs...) - } else { - owners = append(owners, ow) + } + if !found { + out = append(out, machine) } } - return owners, nil + return out, nil } -// expandGroup will return the list of namespace inside the group -// after some validation -func (h *Headscale) expandGroup(group string) ([]string, error) { - gs, ok := h.aclPolicy.Groups[group] - if !ok { - return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) - } - for _, g := range gs { - if strings.HasPrefix(g, "group:") { - return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) - } - } - return gs, nil -} - -func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { +func expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { if portsStr == "*" { return &[]tailcfg.PortRange{ {First: portRangeBegin, Last: portRangeEnd}, @@ -344,3 +338,50 @@ func (h *Headscale) expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { return &ports, nil } + +func listMachinesInNamespace(machines []Machine, namespace string) []Machine { + out := []Machine{} + for _, machine := range machines { + if machine.Namespace.Name == namespace { + out = append(out, machine) + } + } + return out +} + +// expandTagOwners will return a list of namespace. An owner can be either a namespace or a group +// a group cannot be composed of groups +func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { + var owners []string + ows, ok := aclPolicy.TagOwners[tag] + if !ok { + return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) + } + for _, ow := range ows { + if strings.HasPrefix(ow, "group:") { + gs, err := expandGroup(aclPolicy, ow) + if err != nil { + return []string{}, err + } + owners = append(owners, gs...) + } else { + owners = append(owners, ow) + } + } + return owners, nil +} + +// expandGroup will return the list of namespace inside the group +// after some validation +func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { + gs, ok := aclPolicy.Groups[group] + if !ok { + return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + } + for _, g := range gs { + if strings.HasPrefix(g, "group:") { + return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + } + } + return gs, nil +} diff --git a/acls_test.go b/acls_test.go index f2fb6a03..8bedb47d 100644 --- a/acls_test.go +++ b/acls_test.go @@ -2,10 +2,13 @@ package headscale import ( "errors" + "reflect" + "testing" "gopkg.in/check.v1" "gorm.io/datatypes" "inet.af/netaddr" + "tailscale.com/tailcfg" ) func (s *Suite) TestWrongPath(c *check.C) { @@ -267,9 +270,16 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { } err = app.UpdateACLRules() c.Assert(err, check.IsNil) - c.Logf("Rules: %v", app.aclRules) c.Assert(app.aclRules, check.HasLen, 1) - c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 0) + c.Assert(app.aclRules[0].SrcIPs, check.HasLen, 1) + c.Assert(app.aclRules[0].SrcIPs[0], check.Equals, "100.64.0.2") + c.Assert(app.aclRules[0].DstPorts, check.HasLen, 2) + c.Assert(app.aclRules[0].DstPorts[0].Ports.First, check.Equals, uint16(80)) + c.Assert(app.aclRules[0].DstPorts[0].Ports.Last, check.Equals, uint16(80)) + c.Assert(app.aclRules[0].DstPorts[0].IP, check.Equals, "100.64.0.1") + c.Assert(app.aclRules[0].DstPorts[1].Ports.First, check.Equals, uint16(443)) + c.Assert(app.aclRules[0].DstPorts[1].Ports.Last, check.Equals, uint16(443)) + c.Assert(app.aclRules[0].DstPorts[1].IP, check.Equals, "100.64.0.1") } func (s *Suite) TestPortRange(c *check.C) { @@ -385,3 +395,510 @@ func (s *Suite) TestPortGroup(c *check.C) { c.Assert(len(ips), check.Equals, 1) c.Assert(rules[0].SrcIPs[0], check.Equals, ips[0].String()) } + +func Test_expandGroup(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + group string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "simple test", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + }, + group: "group:test", + }, + want: []string{"g1", "foo", "test"}, + wantErr: false, + }, + { + name: "InexistantGroup", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + }, + group: "group:bar", + }, + want: []string{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandGroup(tt.args.aclPolicy, tt.args.group) + if (err != nil) != tt.wantErr { + t.Errorf("expandGroup() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandGroup() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandTagOwners(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + tag string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "simple tag", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"namespace1"}}, + }, + tag: "tag:test", + }, + want: []string{"namespace1"}, + wantErr: false, + }, + { + name: "tag and group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"n1", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + }, + tag: "tag:test", + }, + want: []string{"n1", "bar"}, + wantErr: false, + }, + { + name: "namespace and group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"n1", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{"n1", "bar", "home"}, + wantErr: false, + }, + { + name: "invalid tag", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:foo": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{}, + wantErr: true, + }, + { + name: "invalid group", + args: args{ + aclPolicy: ACLPolicy{ + Groups: Groups{"group:bar": []string{"n1", "foo"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + }, + tag: "tag:test", + }, + want: []string{}, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandTagOwners(tt.args.aclPolicy, tt.args.tag) + if (err != nil) != tt.wantErr { + t.Errorf("expandTagOwners() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandTagOwners() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandPorts(t *testing.T) { + type args struct { + portsStr string + } + tests := []struct { + name string + args args + want *[]tailcfg.PortRange + wantErr bool + }{ + { + name: "wildcard", + args: args{portsStr: "*"}, + want: &[]tailcfg.PortRange{ + {First: portRangeBegin, Last: portRangeEnd}, + }, + wantErr: false, + }, + { + name: "two ports", + args: args{portsStr: "80,443"}, + want: &[]tailcfg.PortRange{ + {First: 80, Last: 80}, + {First: 443, Last: 443}, + }, + wantErr: false, + }, + { + name: "a range and a port", + args: args{portsStr: "80-1024,443"}, + want: &[]tailcfg.PortRange{ + {First: 80, Last: 1024}, + {First: 443, Last: 443}, + }, + wantErr: false, + }, + { + name: "out of bounds", + args: args{portsStr: "854038"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port", + args: args{portsStr: "85a38"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port in first", + args: args{portsStr: "a-80"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port in last", + args: args{portsStr: "80-85a38"}, + want: nil, + wantErr: true, + }, + { + name: "wrong port format", + args: args{portsStr: "80-85a38-3"}, + want: nil, + wantErr: true, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandPorts(tt.args.portsStr) + if (err != nil) != tt.wantErr { + t.Errorf("expandPorts() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandPorts() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_listMachinesInNamespace(t *testing.T) { + type args struct { + machines []Machine + namespace string + } + tests := []struct { + name string + args args + want []Machine + }{ + { + name: "1 machine in namespace", + args: args{ + machines: []Machine{ + {Namespace: Namespace{Name: "test"}}, + }, + namespace: "test", + }, + want: []Machine{ + {Namespace: Namespace{Name: "test"}}, + }, + }, + { + name: "3 machines, 2 in namespace", + args: args{ + machines: []Machine{ + {ID: 1, Namespace: Namespace{Name: "test"}}, + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + }, + }, + { + name: "5 machines, 0 in namespace", + args: args{ + machines: []Machine{ + {ID: 1, Namespace: Namespace{Name: "test"}}, + {ID: 2, Namespace: Namespace{Name: "foo"}}, + {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 4, Namespace: Namespace{Name: "foo"}}, + {ID: 5, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "bar", + }, + want: []Machine{}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual(got, tt.want) { + t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_expandAlias(t *testing.T) { + type args struct { + machines []Machine + aclPolicy ACLPolicy + alias string + } + tests := []struct { + name string + args args + want []string + wantErr bool + }{ + { + name: "wildcard", + args: args{ + alias: "*", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.78.84.227")}}, + }, + aclPolicy: ACLPolicy{}, + }, + want: []string{"*"}, + wantErr: false, + }, + { + name: "simple group", + args: args{ + alias: "group:foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + }, + }, + want: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + wantErr: false, + }, + { + name: "wrong group", + args: args{ + alias: "group:test", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + }, + }, + want: []string{}, + wantErr: true, + }, + { + name: "simple ipaddress", + args: args{ + alias: "10.0.0.3", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.3"}, + wantErr: false, + }, + { + name: "private network", + args: args{ + alias: "homeNetwork", + machines: []Machine{}, + aclPolicy: ACLPolicy{ + Hosts: Hosts{"homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24")}, + }, + }, + want: []string{"192.168.1.0/24"}, + wantErr: false, + }, + { + name: "simple host", + args: args{ + alias: "10.0.0.1", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.1"}, + wantErr: false, + }, + { + name: "simple CIDR", + args: args{ + alias: "10.0.0.0/16", + machines: []Machine{}, + aclPolicy: ACLPolicy{}, + }, + want: []string{"10.0.0.0/16"}, + wantErr: false, + }, + { + name: "simple tag", + args: args{ + alias: "tag:test", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + }, + want: []string{"100.64.0.1", "100.64.0.2"}, + wantErr: false, + }, + { + name: "No tag defined", + args: args{ + alias: "tag:foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + }, + aclPolicy: ACLPolicy{ + Groups: Groups{"group:foo": []string{"foo", "bar"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + }, + }, + want: []string{}, + wantErr: true, + }, + { + name: "list host in namespace without correctly tagged servers", + args: args{ + alias: "foo", + machines: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + }, + want: []string{"100.64.0.4"}, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := expandAlias(tt.args.machines, tt.args.aclPolicy, tt.args.alias) + if (err != nil) != tt.wantErr { + t.Errorf("expandAlias() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("expandAlias() = %v, want %v", got, tt.want) + } + }) + } +} + +func Test_excludeCorrectlyTaggedNodes(t *testing.T) { + type args struct { + aclPolicy ACLPolicy + nodes []Machine + namespace string + } + tests := []struct { + name string + args args + want []Machine + wantErr bool + }{ + { + name: "exclude nodes with valid tags", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:test": []string{"foo"}}, + }, + nodes: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + wantErr: false, + }, + { + name: "all nodes have invalid tags, don't exclude them", + args: args{ + aclPolicy: ACLPolicy{ + TagOwners: TagOwners{"tag:foo": []string{"foo"}}, + }, + nodes: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + namespace: "foo", + }, + want: []Machine{ + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, + {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := excludeCorrectlyTaggedNodes(tt.args.aclPolicy, tt.args.nodes, tt.args.namespace) + if (err != nil) != tt.wantErr { + t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/machine.go b/machine.go index 231c179d..01fc9276 100644 --- a/machine.go +++ b/machine.go @@ -119,6 +119,19 @@ func (machine Machine) isExpired() bool { return time.Now().UTC().After(*machine.Expiry) } +func (h *Headscale) ListAllMachines() ([]Machine, error) { + machines := []Machine{} + if err := h.db.Preload("AuthKey"). + Preload("AuthKey.Namespace"). + Preload("Namespace"). + Where("registered"). + Find(&machines).Error; err != nil { + return nil, err + } + + return machines, nil +} + func containsAddresses(inputs []string, addrs MachineAddresses) bool { for _, addr := range addrs.ToStringSlice() { if containsString(inputs, addr) { From 7b5ba9f78156b7ef1abe3abf9bc0d731396488b5 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 13:54:44 +0100 Subject: [PATCH 07/38] docs(acl): add configuration example to explain acls --- docs/README.md | 8 ++++ docs/acls.md | 126 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 134 insertions(+) create mode 100644 docs/acls.md diff --git a/docs/README.md b/docs/README.md index 1ac15221..4b5d0842 100644 --- a/docs/README.md +++ b/docs/README.md @@ -39,6 +39,14 @@ use namespaces (which are the equivalent to user/logins in Tailscale.com). Please check https://tailscale.com/kb/1018/acls/, and `./tests/acls/` in this repo for working examples. +When using ACL's the Namespace borders are no longer applied. All machines +whichever the Namespace have the ability to communicate with other hosts as +long as the ACL's permits this exchange. + +The [ACLs](acls.md) document should help understand a fictional case of setting +up ACLs in a small company. All concepts presented in this document could be +applied outside of business oriented usage. + ### Apple devices An endpoint with information on how to connect your Apple devices (currently macOS only) is available at `/apple` on your running instance. diff --git a/docs/acls.md b/docs/acls.md new file mode 100644 index 00000000..89e8b557 --- /dev/null +++ b/docs/acls.md @@ -0,0 +1,126 @@ + +# ACLs use case example + +Let's build an example use case for a small business (It may be the place where +ACL's are the most useful). + +We have a small company with a boss, an admin, two developers and an intern. + +The boss should have access to all servers but not to the users hosts. Admin +should also have access to all hosts except that their permissions should be +limited to maintaining the hosts (for example purposes). The developers can do +anything they want on dev hosts, but only watch on productions hosts. Intern +can only interact with the development servers. + +Each user have at least a device connected to the network and we have some +servers. + +- database.prod +- database.dev +- app-server1.prod +- app-server1.dev +- billing.internal + +## Setup of the network + +Let's create the namespaces. Each user should have his own namespace. The users +here are represented as namespaces. + +```bash +headscale namespaces create boss +headscale namespaces create admin1 +headscale namespaces create dev1 +headscale namespaces create dev2 +headscale namespaces create intern1 +``` + +We don't need to create namespaces for the servers because the servers will be +tagged. When registering the servers we will need to add the flag +`--advertised-tags=tag:,tag:`, and the user (namespace) that is +registering the server should be allowed to do it. Since anyone can add tags to +a server they can register, the check of the tags is done on headscale server +and only valid tags are applied. A tag is valid if the namespace that is +registering it is allowed to do it. + +Here are the ACL's to implement the same permissions as above: + +```json +{ + // groups are collections of users having a common scope. A user can be in multiple groups + // groups cannot be composed of groups + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1","dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"], + }, + // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. + // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) + // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) + "tagOwners": { + // the administrators can add servers in production + "tag:prod-databases": ["group:admin"], + "tag:prod-app-servers": ["group:admin"], + + // the boss can tag any server as internal + "tag:internal": ["group:boss"], + + // dev can add servers for dev purposes as well as admins + "tag:dev-databases": ["group:admin","group:dev"], + "tag:dev-app-servers": ["group:admin", "group:dev"], + + // interns cannot add servers + }, + "acls": [ + // boss have access to all servers + {"action":"accept", + "users":["group:boss"], + "ports":[ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*", + ] + }, + + // admin have only access to administrative ports of the servers + {"action":"accept", + "users":["group:admin"], + "ports":[ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22", + ] + }, + + // developers have access to databases servers and application servers on all ports + // they can only view the applications servers in prod and have no access to databases servers in production + {"action":"accept", "users":["group:dev"], "ports":[ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443", + ] + }, + + // servers should be able to talk to database. Database should not be able to initiate connections to + // applications servers + {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, + {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + + // interns have access to dev-app-servers only in reading mode + {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, + + // We still have to allow internal namespaces communications since nothing guarantees that each user have + // their own namespaces. + {"action":"accept", "users":["boss"], "ports":["boss:*"]}, + {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, + {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, + {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, + {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, + ] +} +``` + From aceaba60f174703eedefa2b9775e8c4026000988 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 14:02:18 +0100 Subject: [PATCH 08/38] docs(changelog): bump changelog --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6e44161..16427017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ **TBD (TBD):** +**BREAKING**: +- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. + + **0.13.0 (2022-xx-xx):** **Features**: From 9cedbbafd46ad3034967a25f1901f8fe04ee4bf7 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 15:26:54 +0100 Subject: [PATCH 09/38] chore(all): update some files for linter --- acls.go | 31 +++++++++------ acls_test.go | 101 +++++++++++++++++++++++++----------------------- api.go | 22 ++++++++++- dns.go | 4 +- machine.go | 13 ++++--- machine_test.go | 3 +- poll.go | 17 +++++++- 7 files changed, 118 insertions(+), 73 deletions(-) diff --git a/acls.go b/acls.go index 9dd1260d..3d6b1945 100644 --- a/acls.go +++ b/acls.go @@ -20,7 +20,6 @@ const ( errInvalidUserSection = Error("invalid user section") errInvalidGroup = Error("invalid group") errInvalidTag = Error("invalid tag") - errInvalidNamespace = Error("invalid namespace") errInvalidPortFormat = Error("invalid port format") ) @@ -69,6 +68,7 @@ func (h *Headscale) LoadACLPolicy(path string) error { } h.aclPolicy = &policy + return h.UpdateACLRules() } @@ -79,6 +79,7 @@ func (h *Headscale) UpdateACLRules() error { } log.Trace().Interface("ACL", rules).Msg("ACL rules generated") h.aclRules = rules + return nil } @@ -182,7 +183,7 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a namespace // - a group // - a tag -// and transform these in IPAddresses +// and transform these in IPAddresses. func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { ips := []string{} if alias == "*" { @@ -200,6 +201,7 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin ips = append(ips, node.IPAddresses.ToStringSlice()...) } } + return ips, nil } @@ -225,6 +227,7 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin } } } + return ips, nil } @@ -276,6 +279,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace for _, machine := range nodes { if len(machine.HostInfo) == 0 { out = append(out, machine) + continue } hi, err := machine.GetHostInfo() @@ -286,6 +290,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace for _, t := range hi.RequestTags { if containsString(tags, t) { found = true + break } } @@ -293,6 +298,7 @@ func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace out = append(out, machine) } } + return out, nil } @@ -346,42 +352,45 @@ func listMachinesInNamespace(machines []Machine, namespace string) []Machine { out = append(out, machine) } } + return out } // expandTagOwners will return a list of namespace. An owner can be either a namespace or a group -// a group cannot be composed of groups +// a group cannot be composed of groups. func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { var owners []string ows, ok := aclPolicy.TagOwners[tag] if !ok { return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) } - for _, ow := range ows { - if strings.HasPrefix(ow, "group:") { - gs, err := expandGroup(aclPolicy, ow) + for _, owner := range ows { + if strings.HasPrefix(owner, "group:") { + gs, err := expandGroup(aclPolicy, owner) if err != nil { return []string{}, err } owners = append(owners, gs...) } else { - owners = append(owners, ow) + owners = append(owners, owner) } } + return owners, nil } // expandGroup will return the list of namespace inside the group -// after some validation +// after some validation. func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { - gs, ok := aclPolicy.Groups[group] + groups, ok := aclPolicy.Groups[group] if !ok { return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) } - for _, g := range gs { + for _, g := range groups { if strings.HasPrefix(g, "group:") { return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) } } - return gs, nil + + return groups, nil } diff --git a/acls_test.go b/acls_test.go index 8bedb47d..786de0fc 100644 --- a/acls_test.go +++ b/acls_test.go @@ -94,7 +94,7 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) { // this test should validate that we can expand a group in a TagOWner section and // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. -// the tag is matched in the Users section +// the tag is matched in the Users section. func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -104,7 +104,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") machine := Machine{ ID: 0, MachineKey: "foo", @@ -116,7 +116,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -136,7 +136,7 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { // this test should validate that we can expand a group in a TagOWner section and // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. -// the tag is matched in the Ports section +// the tag is matched in the Ports section. func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -146,7 +146,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -158,7 +158,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -178,7 +178,7 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { // need a test with: // tag on a host that isn't owned by a tag owners. So the namespace -// of the host should be valid +// of the host should be valid. func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { namespace, err := app.CreateNamespace("foo") c.Assert(err, check.IsNil) @@ -188,7 +188,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -200,7 +200,7 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -229,7 +229,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { _, err = app.GetMachine("foo", "webserver") c.Assert(err, check.NotNil) - b := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") machine := Machine{ ID: 1, MachineKey: "foo", @@ -241,11 +241,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) _, err = app.GetMachine("foo", "user") - b = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") + hostInfo = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") c.Assert(err, check.NotNil) machine = Machine{ ID: 2, @@ -258,7 +258,7 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { Registered: true, RegisterMethod: RegisterMethodAuthKey, AuthKeyID: uint(pak.ID), - HostInfo: datatypes.JSON(b), + HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) @@ -430,15 +430,16 @@ func Test_expandGroup(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandGroup(tt.args.aclPolicy, tt.args.group) - if (err != nil) != tt.wantErr { - t.Errorf("expandGroup() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandGroup(test.args.aclPolicy, test.args.group) + if (err != nil) != test.wantErr { + t.Errorf("expandGroup() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandGroup() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandGroup() = %v, want %v", got, test.want) } }) } @@ -514,15 +515,16 @@ func Test_expandTagOwners(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandTagOwners(tt.args.aclPolicy, tt.args.tag) - if (err != nil) != tt.wantErr { - t.Errorf("expandTagOwners() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandTagOwners(test.args.aclPolicy, test.args.tag) + if (err != nil) != test.wantErr { + t.Errorf("expandTagOwners() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandTagOwners() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandTagOwners() = %v, want %v", got, test.want) } }) } @@ -595,15 +597,16 @@ func Test_expandPorts(t *testing.T) { wantErr: true, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandPorts(tt.args.portsStr) - if (err != nil) != tt.wantErr { - t.Errorf("expandPorts() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandPorts(test.args.portsStr) + if (err != nil) != test.wantErr { + t.Errorf("expandPorts() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandPorts() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandPorts() = %v, want %v", got, test.want) } }) } @@ -824,15 +827,16 @@ func Test_expandAlias(t *testing.T) { wantErr: false, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := expandAlias(tt.args.machines, tt.args.aclPolicy, tt.args.alias) - if (err != nil) != tt.wantErr { - t.Errorf("expandAlias() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := expandAlias(test.args.machines, test.args.aclPolicy, test.args.alias) + if (err != nil) != test.wantErr { + t.Errorf("expandAlias() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("expandAlias() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("expandAlias() = %v, want %v", got, test.want) } }) } @@ -889,15 +893,16 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { wantErr: false, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := excludeCorrectlyTaggedNodes(tt.args.aclPolicy, tt.args.nodes, tt.args.namespace) - if (err != nil) != tt.wantErr { - t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, tt.wantErr) + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + got, err := excludeCorrectlyTaggedNodes(test.args.aclPolicy, test.args.nodes, test.args.namespace) + if (err != nil) != test.wantErr { + t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, test.wantErr) + return } - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, tt.want) + if !reflect.DeepEqual(got, test.want) { + t.Errorf("excludeCorrectlyTaggedNodes() = %v, want %v", got, test.want) } }) } diff --git a/api.go b/api.go index 020ded01..073be5e2 100644 --- a/api.go +++ b/api.go @@ -261,7 +261,16 @@ func (h *Headscale) getMapResponse( var respBody []byte if req.Compress == "zstd" { - src, _ := json.Marshal(resp) + src, err := json.Marshal(resp) + if err != nil { + log.Error(). + Caller(). + Str("func", "getMapResponse"). + Err(err). + Msg("Failed to marshal response for the client") + + return nil, err + } encoder, _ := zstd.NewWriter(nil) srcCompressed := encoder.EncodeAll(src, nil) @@ -290,7 +299,16 @@ func (h *Headscale) getMapKeepAliveResponse( var respBody []byte var err error if mapRequest.Compress == "zstd" { - src, _ := json.Marshal(mapResponse) + src, err := json.Marshal(mapResponse) + if err != nil { + log.Error(). + Caller(). + Str("func", "getMapKeepAliveResponse"). + Err(err). + Msg("Failed to marshal keepalive response for the client") + + return nil, err + } encoder, _ := zstd.NewWriter(nil) srcCompressed := encoder.EncodeAll(src, nil) respBody = h.privateKey.SealTo(machineKey, srcCompressed) diff --git a/dns.go b/dns.go index 37daa884..085a14e2 100644 --- a/dns.go +++ b/dns.go @@ -165,7 +165,7 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine baseDomain, ), ) @@ -176,7 +176,7 @@ func getMapResponseDNSConfig( namespaceSet.Add(p.Namespace) } for _, namespace := range namespaceSet.List() { - dnsRoute := fmt.Sprintf("%s.%s", namespace.(Namespace).Name, baseDomain) + var dnsRoute string = fmt.Sprintf("%v.%v", namespace.(Namespace).Name, baseDomain) dnsConfig.Routes[dnsRoute] = nil } } else { diff --git a/machine.go b/machine.go index 01fc9276..cb70bf12 100644 --- a/machine.go +++ b/machine.go @@ -138,6 +138,7 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return true } } + return false } @@ -174,20 +175,20 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know // how to talk to node A and then add the peering resource. - for _, m := range machines { + for _, mchn := range machines { for _, rule := range h.aclRules { var dst []string for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, m.IPAddresses) || containsString(dst, "*"))) || - (containsAddresses(rule.SrcIPs, m.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { - mMachines[m.ID] = m + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, mchn.IPAddresses) || containsString(dst, "*"))) || + (containsAddresses(rule.SrcIPs, mchn.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + mMachines[mchn.ID] = mchn } } } - var authorizedMachines Machines + authorizedMachines := make([]Machine, 0, len(mMachines)) for _, m := range mMachines { authorizedMachines = append(authorizedMachines, m) } @@ -694,7 +695,7 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - strings.Replace(machine.Namespace.Name, "@", ".", -1), // Replace @ with . for valid domain for machine + strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine baseDomain, ) } else { diff --git a/machine_test.go b/machine_test.go index 203289ac..df00067b 100644 --- a/machine_test.go +++ b/machine_test.go @@ -161,7 +161,7 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { key *PreAuthKey } - var stor []base + stor := make([]base, 0) for _, name := range []string{"test", "admin"} { namespace, err := app.CreateNamespace(name) @@ -169,7 +169,6 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) stor = append(stor, base{namespace, pak}) - } _, err := app.GetMachineByID(0) diff --git a/poll.go b/poll.go index c2a51d11..f00f7484 100644 --- a/poll.go +++ b/poll.go @@ -85,7 +85,10 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { Str("machine", machine.Name). Msg("Found machine in database") - hostinfo, _ := json.Marshal(req.Hostinfo) + hostinfo, err := json.Marshal(req.Hostinfo) + if err != nil { + return + } machine.Name = req.Hostinfo.Hostname machine.HostInfo = datatypes.JSON(hostinfo) machine.DiscoKey = DiscoPublicKeyStripPrefix(req.DiscoKey) @@ -106,7 +109,17 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { // The intended use is for clients to discover the DERP map at start-up // before their first real endpoint update. if !req.ReadOnly { - endpoints, _ := json.Marshal(req.Endpoints) + endpoints, err := json.Marshal(req.Endpoints) + if err != nil { + log.Error(). + Caller(). + Str("func", "PollNetMapHandler"). + Err(err). + Msg("Failed to mashal requested endpoints for the client") + ctx.String(http.StatusInternalServerError, ":(") + + return + } machine.Endpoints = datatypes.JSON(endpoints) machine.LastSeen = &now } From d8c4c3163b6fe9bba05fa2dd2566910ebf749c31 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 15:54:51 +0100 Subject: [PATCH 10/38] chore(fmt): apply make fmt command --- CHANGELOG.md | 2 +- acls.go | 35 +++++- acls_test.go | 302 +++++++++++++++++++++++++++++++++++++++++------- dns.go | 6 +- docs/acls.md | 155 ++++++++++++++----------- machine.go | 11 +- machine_test.go | 12 +- poll.go | 6 +- 8 files changed, 399 insertions(+), 130 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16427017..62808b84 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,8 @@ **TBD (TBD):** **BREAKING**: -- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. +- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. **0.13.0 (2022-xx-xx):** diff --git a/acls.go b/acls.go index 3d6b1945..d5d39889 100644 --- a/acls.go +++ b/acls.go @@ -129,7 +129,11 @@ func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { return rules, nil } -func (h *Headscale) generateACLPolicySrcIP(machines []Machine, aclPolicy ACLPolicy, u string) ([]string, error) { +func (h *Headscale) generateACLPolicySrcIP( + machines []Machine, + aclPolicy ACLPolicy, + u string, +) ([]string, error) { return expandAlias(machines, aclPolicy, u) } @@ -184,7 +188,11 @@ func (h *Headscale) generateACLPolicyDestPorts( // - a group // - a tag // and transform these in IPAddresses. -func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]string, error) { +func expandAlias( + machines []Machine, + aclPolicy ACLPolicy, + alias string, +) ([]string, error) { ips := []string{} if alias == "*" { return []string{"*"}, nil @@ -267,7 +275,11 @@ func expandAlias(machines []Machine, aclPolicy ACLPolicy, alias string) ([]strin // excludeCorrectlyTaggedNodes will remove from the list of input nodes the ones // that are correctly tagged since they should not be listed as being in the namespace // we assume in this function that we only have nodes from 1 namespace. -func excludeCorrectlyTaggedNodes(aclPolicy ACLPolicy, nodes []Machine, namespace string) ([]Machine, error) { +func excludeCorrectlyTaggedNodes( + aclPolicy ACLPolicy, + nodes []Machine, + namespace string, +) ([]Machine, error) { out := []Machine{} tags := []string{} for tag, ns := range aclPolicy.TagOwners { @@ -362,7 +374,11 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { var owners []string ows, ok := aclPolicy.TagOwners[tag] if !ok { - return []string{}, fmt.Errorf("%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", errInvalidTag, tag) + return []string{}, fmt.Errorf( + "%w. %v isn't owned by a TagOwner. Please add one first. https://tailscale.com/kb/1018/acls/#tag-owners", + errInvalidTag, + tag, + ) } for _, owner := range ows { if strings.HasPrefix(owner, "group:") { @@ -384,11 +400,18 @@ func expandTagOwners(aclPolicy ACLPolicy, tag string) ([]string, error) { func expandGroup(aclPolicy ACLPolicy, group string) ([]string, error) { groups, ok := aclPolicy.Groups[group] if !ok { - return []string{}, fmt.Errorf("group %v isn't registered. %w", group, errInvalidGroup) + return []string{}, fmt.Errorf( + "group %v isn't registered. %w", + group, + errInvalidGroup, + ) } for _, g := range groups { if strings.HasPrefix(g, "group:") { - return []string{}, fmt.Errorf("%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", errInvalidGroup) + return []string{}, fmt.Errorf( + "%w. A group cannot be composed of groups. https://tailscale.com/kb/1018/acls/#groups", + errInvalidGroup, + ) } } diff --git a/acls_test.go b/acls_test.go index 786de0fc..f8407d42 100644 --- a/acls_test.go +++ b/acls_test.go @@ -72,7 +72,10 @@ func (s *Suite) TestInvalidAction(c *check.C) { func (s *Suite) TestInvalidGroupInGroup(c *check.C) { // this ACL is wrong because the group in users sections doesn't exist app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo"}, "group:error": []string{"foo", "group:test"}}, + Groups: Groups{ + "group:test": []string{"foo"}, + "group:error": []string{"foo", "group:test"}, + }, ACLs: []ACL{ {Action: "accept", Users: []string{"group:error"}, Ports: []string{"*:*"}}, }, @@ -104,7 +107,9 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ) machine := Machine{ ID: 0, MachineKey: "foo", @@ -146,7 +151,9 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -188,7 +195,9 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { _, err = app.GetMachine("foo", "testmachine") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -229,7 +238,9 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { _, err = app.GetMachine("foo", "webserver") c.Assert(err, check.NotNil) - hostInfo := []byte("{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}") + hostInfo := []byte( + "{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}", + ) machine := Machine{ ID: 1, MachineKey: "foo", @@ -265,7 +276,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { app.aclPolicy = &ACLPolicy{ TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, ACLs: []ACL{ - {Action: "accept", Users: []string{"foo"}, Ports: []string{"tag:webapp:80,443"}}, + { + Action: "accept", + Users: []string{"foo"}, + Ports: []string{"tag:webapp:80,443"}, + }, }, } err = app.UpdateACLRules() @@ -411,7 +426,10 @@ func Test_expandGroup(t *testing.T) { name: "simple test", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + Groups: Groups{ + "group:test": []string{"g1", "foo", "test"}, + "group:foo": []string{"foo", "test"}, + }, }, group: "group:test", }, @@ -422,7 +440,10 @@ func Test_expandGroup(t *testing.T) { name: "InexistantGroup", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:test": []string{"g1", "foo", "test"}, "group:foo": []string{"foo", "test"}}, + Groups: Groups{ + "group:test": []string{"g1", "foo", "test"}, + "group:foo": []string{"foo", "test"}, + }, }, group: "group:bar", }, @@ -666,7 +687,10 @@ func Test_listMachinesInNamespace(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual(got, tt.want) { + if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual( + got, + tt.want, + ) { t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) } }) @@ -691,7 +715,11 @@ func Test_expandAlias(t *testing.T) { alias: "*", machines: []Machine{ {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.78.84.227")}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.78.84.227"), + }, + }, }, aclPolicy: ACLPolicy{}, }, @@ -703,10 +731,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -720,10 +768,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "group:test", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -748,7 +816,9 @@ func Test_expandAlias(t *testing.T) { alias: "homeNetwork", machines: []Machine{}, aclPolicy: ACLPolicy{ - Hosts: Hosts{"homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24")}, + Hosts: Hosts{ + "homeNetwork": netaddr.MustParseIPPrefix("192.168.1.0/24"), + }, }, }, want: []string{"192.168.1.0/24"}, @@ -779,10 +849,36 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:test", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:test": []string{"foo"}}, @@ -796,10 +892,30 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "tag:foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "test"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "test"}, + }, }, aclPolicy: ACLPolicy{ Groups: Groups{"group:foo": []string{"foo", "bar"}}, @@ -814,10 +930,36 @@ func Test_expandAlias(t *testing.T) { args: args{ alias: "foo", machines: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, Namespace: Namespace{Name: "bar"}}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "bar"}, + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, aclPolicy: ACLPolicy{ TagOwners: TagOwners{"tag:test": []string{"foo"}}, @@ -829,7 +971,11 @@ func Test_expandAlias(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := expandAlias(test.args.machines, test.args.aclPolicy, test.args.alias) + got, err := expandAlias( + test.args.machines, + test.args.aclPolicy, + test.args.alias, + ) if (err != nil) != test.wantErr { t.Errorf("expandAlias() error = %v, wantErr %v", err, test.wantErr) @@ -861,14 +1007,38 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:test": []string{"foo"}}, }, nodes: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, namespace: "foo", }, want: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, + Namespace: Namespace{Name: "foo"}, + }, }, wantErr: false, }, @@ -879,25 +1049,69 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { TagOwners: TagOwners{"tag:foo": []string{"foo"}}, }, nodes: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "foo"}, + }, }, namespace: "foo", }, want: []Machine{ - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, Namespace: Namespace{Name: "foo"}, HostInfo: []byte("{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}")}, - {IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, Namespace: Namespace{Name: "foo"}}, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "foo"}, + HostInfo: []byte( + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + ), + }, + { + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, + Namespace: Namespace{Name: "foo"}, + }, }, wantErr: false, }, } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - got, err := excludeCorrectlyTaggedNodes(test.args.aclPolicy, test.args.nodes, test.args.namespace) + got, err := excludeCorrectlyTaggedNodes( + test.args.aclPolicy, + test.args.nodes, + test.args.namespace, + ) if (err != nil) != test.wantErr { - t.Errorf("excludeCorrectlyTaggedNodes() error = %v, wantErr %v", err, test.wantErr) + t.Errorf( + "excludeCorrectlyTaggedNodes() error = %v, wantErr %v", + err, + test.wantErr, + ) return } diff --git a/dns.go b/dns.go index 085a14e2..be6238f8 100644 --- a/dns.go +++ b/dns.go @@ -165,7 +165,11 @@ func getMapResponseDNSConfig( dnsConfig.Domains, fmt.Sprintf( "%s.%s", - strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine + strings.ReplaceAll( + machine.Namespace.Name, + "@", + ".", + ), // Replace @ with . for valid domain for machine baseDomain, ), ) diff --git a/docs/acls.md b/docs/acls.md index 89e8b557..63e7c6b8 100644 --- a/docs/acls.md +++ b/docs/acls.md @@ -1,4 +1,3 @@ - # ACLs use case example Let's build an example use case for a small business (It may be the place where @@ -46,81 +45,97 @@ Here are the ACL's to implement the same permissions as above: ```json { - // groups are collections of users having a common scope. A user can be in multiple groups - // groups cannot be composed of groups - "groups": { - "group:boss": ["boss"], - "group:dev": ["dev1","dev2"], - "group:admin": ["admin1"], - "group:intern": ["intern1"], + // groups are collections of users having a common scope. A user can be in multiple groups + // groups cannot be composed of groups + "groups": { + "group:boss": ["boss"], + "group:dev": ["dev1", "dev2"], + "group:admin": ["admin1"], + "group:intern": ["intern1"] + }, + // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. + // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) + // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) + "tagOwners": { + // the administrators can add servers in production + "tag:prod-databases": ["group:admin"], + "tag:prod-app-servers": ["group:admin"], + + // the boss can tag any server as internal + "tag:internal": ["group:boss"], + + // dev can add servers for dev purposes as well as admins + "tag:dev-databases": ["group:admin", "group:dev"], + "tag:dev-app-servers": ["group:admin", "group:dev"] + + // interns cannot add servers + }, + "acls": [ + // boss have access to all servers + { + "action": "accept", + "users": ["group:boss"], + "ports": [ + "tag:prod-databases:*", + "tag:prod-app-servers:*", + "tag:internal:*", + "tag:dev-databases:*", + "tag:dev-app-servers:*" + ] }, - // tagOwners in tailscale is an association between a TAG and the people allowed to set this TAG on a server. - // This is documented [here](https://tailscale.com/kb/1068/acl-tags#defining-a-tag) - // and explained [here](https://tailscale.com/blog/rbac-like-it-was-meant-to-be/) - "tagOwners": { - // the administrators can add servers in production - "tag:prod-databases": ["group:admin"], - "tag:prod-app-servers": ["group:admin"], - // the boss can tag any server as internal - "tag:internal": ["group:boss"], - - // dev can add servers for dev purposes as well as admins - "tag:dev-databases": ["group:admin","group:dev"], - "tag:dev-app-servers": ["group:admin", "group:dev"], - - // interns cannot add servers + // admin have only access to administrative ports of the servers + { + "action": "accept", + "users": ["group:admin"], + "ports": [ + "tag:prod-databases:22", + "tag:prod-app-servers:22", + "tag:internal:22", + "tag:dev-databases:22", + "tag:dev-app-servers:22" + ] }, - "acls": [ - // boss have access to all servers - {"action":"accept", - "users":["group:boss"], - "ports":[ - "tag:prod-databases:*", - "tag:prod-app-servers:*", - "tag:internal:*", - "tag:dev-databases:*", - "tag:dev-app-servers:*", - ] - }, - // admin have only access to administrative ports of the servers - {"action":"accept", - "users":["group:admin"], - "ports":[ - "tag:prod-databases:22", - "tag:prod-app-servers:22", - "tag:internal:22", - "tag:dev-databases:22", - "tag:dev-app-servers:22", - ] - }, + // developers have access to databases servers and application servers on all ports + // they can only view the applications servers in prod and have no access to databases servers in production + { + "action": "accept", + "users": ["group:dev"], + "ports": [ + "tag:dev-databases:*", + "tag:dev-app-servers:*", + "tag:prod-app-servers:80,443" + ] + }, - // developers have access to databases servers and application servers on all ports - // they can only view the applications servers in prod and have no access to databases servers in production - {"action":"accept", "users":["group:dev"], "ports":[ - "tag:dev-databases:*", - "tag:dev-app-servers:*", - "tag:prod-app-servers:80,443", - ] - }, + // servers should be able to talk to database. Database should not be able to initiate connections to + // applications servers + { + "action": "accept", + "users": ["tag:dev-app-servers"], + "ports": ["tag:dev-databases:5432"] + }, + { + "action": "accept", + "users": ["tag:prod-app-servers"], + "ports": ["tag:prod-databases:5432"] + }, - // servers should be able to talk to database. Database should not be able to initiate connections to - // applications servers - {"action":"accept", "users":["tag:dev-app-servers"], "ports":["tag:dev-databases:5432"]}, - {"action":"accept", "users":["tag:prod-app-servers"], "ports":["tag:prod-databases:5432"]}, + // interns have access to dev-app-servers only in reading mode + { + "action": "accept", + "users": ["group:intern"], + "ports": ["tag:dev-app-servers:80,443"] + }, - // interns have access to dev-app-servers only in reading mode - {"action":"accept", "users":["group:intern"], "ports":["tag:dev-app-servers:80,443"]}, - - // We still have to allow internal namespaces communications since nothing guarantees that each user have - // their own namespaces. - {"action":"accept", "users":["boss"], "ports":["boss:*"]}, - {"action":"accept", "users":["dev1"], "ports":["dev1:*"]}, - {"action":"accept", "users":["dev2"], "ports":["dev2:*"]}, - {"action":"accept", "users":["admin1"], "ports":["admin1:*"]}, - {"action":"accept", "users":["intern1"], "ports":["intern1:*"]}, - ] + // We still have to allow internal namespaces communications since nothing guarantees that each user have + // their own namespaces. + { "action": "accept", "users": ["boss"], "ports": ["boss:*"] }, + { "action": "accept", "users": ["dev1"], "ports": ["dev1:*"] }, + { "action": "accept", "users": ["dev2"], "ports": ["dev2:*"] }, + { "action": "accept", "users": ["admin1"], "ports": ["admin1:*"] }, + { "action": "accept", "users": ["intern1"], "ports": ["intern1:*"] } + ] } ``` - diff --git a/machine.go b/machine.go index cb70bf12..ba677f15 100644 --- a/machine.go +++ b/machine.go @@ -192,7 +192,10 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, m := range mMachines { authorizedMachines = append(authorizedMachines, m) } - sort.Slice(authorizedMachines, func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }) + sort.Slice( + authorizedMachines, + func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }, + ) log.Trace(). Caller(). @@ -695,7 +698,11 @@ func (machine Machine) toNode( hostname = fmt.Sprintf( "%s.%s.%s", machine.Name, - strings.ReplaceAll(machine.Namespace.Name, "@", "."), // Replace @ with . for valid domain for machine + strings.ReplaceAll( + machine.Namespace.Name, + "@", + ".", + ), // Replace @ with . for valid domain for machine baseDomain, ) } else { diff --git a/machine_test.go b/machine_test.go index df00067b..f9e58be9 100644 --- a/machine_test.go +++ b/machine_test.go @@ -176,11 +176,13 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { for index := 0; index <= 10; index++ { machine := Machine{ - ID: uint64(index), - MachineKey: "foo" + strconv.Itoa(index), - NodeKey: "bar" + strconv.Itoa(index), - DiscoKey: "faa" + strconv.Itoa(index), - IPAddresses: MachineAddresses{netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1)))}, + ID: uint64(index), + MachineKey: "foo" + strconv.Itoa(index), + NodeKey: "bar" + strconv.Itoa(index), + DiscoKey: "faa" + strconv.Itoa(index), + IPAddresses: MachineAddresses{ + netaddr.MustParseIP(fmt.Sprintf("100.64.0.%v", strconv.Itoa(index+1))), + }, Name: "testmachine" + strconv.Itoa(index), NamespaceID: stor[index%2].namespace.ID, Registered: true, diff --git a/poll.go b/poll.go index f00f7484..96db43f2 100644 --- a/poll.go +++ b/poll.go @@ -97,7 +97,11 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { // update ACLRules with peer informations (to update server tags if necessary) err = h.UpdateACLRules() if err != nil { - log.Error().Caller().Str("func", "handleAuthKey").Str("machine", machine.Name).Err(err) + log.Error(). + Caller(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Err(err) } // From Tailscale client: From 5f642eef76e497c03e0409aefa691d7602822bf3 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 18:24:37 +0100 Subject: [PATCH 11/38] chore(lint): more lint fixing --- acls_test.go | 10 +++++----- dns.go | 10 ++++++++-- utils.go | 1 + 3 files changed, 14 insertions(+), 7 deletions(-) diff --git a/acls_test.go b/acls_test.go index f8407d42..2bd5bf96 100644 --- a/acls_test.go +++ b/acls_test.go @@ -685,13 +685,13 @@ func Test_listMachinesInNamespace(t *testing.T) { want: []Machine{}, }, } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := listMachinesInNamespace(tt.args.machines, tt.args.namespace); !reflect.DeepEqual( + for _, test := range tests { + t.Run(test.name, func(t *testing.T) { + if got := listMachinesInNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( got, - tt.want, + test.want, ) { - t.Errorf("listMachinesInNamespace() = %v, want %v", got, tt.want) + t.Errorf("listMachinesInNamespace() = %v, want %v", got, test.want) } }) } diff --git a/dns.go b/dns.go index be6238f8..45e0faeb 100644 --- a/dns.go +++ b/dns.go @@ -179,8 +179,14 @@ func getMapResponseDNSConfig( for _, p := range peers { namespaceSet.Add(p.Namespace) } - for _, namespace := range namespaceSet.List() { - var dnsRoute string = fmt.Sprintf("%v.%v", namespace.(Namespace).Name, baseDomain) + for _, ns := range namespaceSet.List() { + namespace, ok := ns.(Namespace) + if !ok { + dnsConfig = dnsConfigOrig + + continue + } + dnsRoute := fmt.Sprintf("%v.%v", namespace.Name, baseDomain) dnsConfig.Routes[dnsRoute] = nil } } else { diff --git a/utils.go b/utils.go index 794971a1..3cee5e35 100644 --- a/utils.go +++ b/utils.go @@ -218,6 +218,7 @@ func containsString(ss []string, s string) bool { return true } } + return false } From f073d8f43c0334db46dccdb66083e7c3a07925a5 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 14 Feb 2022 18:32:20 +0100 Subject: [PATCH 12/38] chore(lint): ignore linting on test_expandalias This is a false positive on the way the function is built. Small tests cases are all inside this functions, making it big. --- acls_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/acls_test.go b/acls_test.go index 2bd5bf96..e68a01f6 100644 --- a/acls_test.go +++ b/acls_test.go @@ -697,6 +697,7 @@ func Test_listMachinesInNamespace(t *testing.T) { } } +// nolint func Test_expandAlias(t *testing.T) { type args struct { machines []Machine From 3db88d27de119895bafd78f08e1523d3fd5e7919 Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 22:58:01 +0100 Subject: [PATCH 13/38] github/workflows: init renovatebot --- .github/renovate.json | 7 +++++++ .github/workflows/renovatebot.yml | 26 ++++++++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 .github/renovate.json create mode 100644 .github/workflows/renovatebot.yml diff --git a/.github/renovate.json b/.github/renovate.json new file mode 100644 index 00000000..85962d7e --- /dev/null +++ b/.github/renovate.json @@ -0,0 +1,7 @@ +{ + "extends": ["config:base"]", + "baseBranches": ["main"], + "branchPrefix": "renovateaction", + "extends": ["config:base", ":rebaseStalePrs"], + "enabledManagers": ["dockerfile", "go", "github-actions"] +} diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml new file mode 100644 index 00000000..d6023323 --- /dev/null +++ b/.github/workflows/renovatebot.yml @@ -0,0 +1,26 @@ +--- +name: Renovate +on: + schedule: + - cron: '* * 5,20 * *' #Every 5th and 20th of the month + workflow_dispatch: +jobs: + renovate: + runs-on: ubuntu-latest + steps: + - name: Get token + id: get_token + uses: machine-learning-apps/actions-app-token@master + with: + APP_PEM: ${{ secrets.RENOVATEBOT_SECRET }} + APP_ID: ${{ secrets.RENOVATEBOT_APP_ID }} + + - name: Checkout + uses: actions/checkout@v2.0.0 + + - name: Self-hosted Renovate + uses: renovatebot/github-action@v31.81.2 + with: + configurationFile: .github/renovate.json + token: 'x-access-token:${{ steps.get_token.outputs.app_token }}' + onboarding: false From a19550adbfcab8b0a8044a9ec4cb96530f0ac9ec Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 23:03:03 +0100 Subject: [PATCH 14/38] prettier: renovatebot.yml --- .github/workflows/renovatebot.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml index d6023323..3f912566 100644 --- a/.github/workflows/renovatebot.yml +++ b/.github/workflows/renovatebot.yml @@ -2,8 +2,8 @@ name: Renovate on: schedule: - - cron: '* * 5,20 * *' #Every 5th and 20th of the month - workflow_dispatch: + - cron: "* * 5,20 * *" # Every 5th and 20th of the month + workflow_dispatch: jobs: renovate: runs-on: ubuntu-latest @@ -22,5 +22,5 @@ jobs: uses: renovatebot/github-action@v31.81.2 with: configurationFile: .github/renovate.json - token: 'x-access-token:${{ steps.get_token.outputs.app_token }}' + token: "x-access-token:${{ steps.get_token.outputs.app_token }}" onboarding: false From fe6d47030f42954fc2d8c85712b4318c873f365a Mon Sep 17 00:00:00 2001 From: ohdearaugustin Date: Mon, 14 Feb 2022 23:33:55 +0100 Subject: [PATCH 15/38] renovatebot: configure --- .github/renovate.json | 37 ++++++++++++++++++++++++++++--- .github/workflows/renovatebot.yml | 5 +++-- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 85962d7e..ce38ba96 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -1,7 +1,38 @@ { - "extends": ["config:base"]", "baseBranches": ["main"], - "branchPrefix": "renovateaction", + "username": "renovate-release", + "gitAuthor": "Renovate Bot ", + "branchPrefix": "renovateaction/", + "onboarding": false, "extends": ["config:base", ":rebaseStalePrs"], - "enabledManagers": ["dockerfile", "go", "github-actions"] + "ignorePresets": [":prHourlyLimit2"], + "enabledManagers": ["dockerfile", "gomod", "github-actions","regex" ], + "includeForks": true, + "repositories": ["juanfont/headscale"], + "platform": "github", + "packageRules": [ + { + "matchDatasources": ["go"], + "groupName": "Go modules", + "groupSlug": "gomod", + "separateMajorMinor": false + }, + { + "matchDatasources": ["docker"], + "groupName": "Dockerfiles", + "groupSlug": "dockerfiles" + } + ], + "regexManagers": [ + { + "fileMatch": [ + ".github/workflows/.*.yml$" + ], + "matchStrings": [ + "\\s*go-version:\\s*\"?(?.*?)\"?\\n" + ], + "datasourceTemplate": "golang-version", + "depNameTemplate": "actions/go-version" + } + ] } diff --git a/.github/workflows/renovatebot.yml b/.github/workflows/renovatebot.yml index 3f912566..53b976ca 100644 --- a/.github/workflows/renovatebot.yml +++ b/.github/workflows/renovatebot.yml @@ -19,8 +19,9 @@ jobs: uses: actions/checkout@v2.0.0 - name: Self-hosted Renovate - uses: renovatebot/github-action@v31.81.2 + uses: renovatebot/github-action@v31.81.3 with: configurationFile: .github/renovate.json token: "x-access-token:${{ steps.get_token.outputs.app_token }}" - onboarding: false + # env: + # LOG_LEVEL: "debug" From 4f9ece14c56db2b6baa0767a546b19506b90d832 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 20:47:12 +0100 Subject: [PATCH 16/38] Apply suggestions from code review on changelog Co-authored-by: Kristoffer Dalby --- CHANGELOG.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 62808b84..cd582afd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,9 +2,24 @@ **TBD (TBD):** +**0.14.0 (2022-xx-xx):** + +**UPCOMING BREAKING**: +From the **next** version (`0.15.0`), all machines will be able to communicate regardless of +if they are in the same namespace. This means that the behaviour currently limited to ACLs +will become default. From version `0.15.0`, all limitation of communications must be done +with ACLs. + +This is a part of aligning `headscale`'s behaviour with Tailscale's upstream behaviour. + **BREAKING**: -- ACLs have been rewritten and the behavior is different from before. It's now more aligned to tailscale's view of the feature. Namespaces are viewed as users and can communicate with each others. Tags should now work correctly and adding a host to Headscale should now reload the rules. The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features. +- ACLs have been rewritten to align with the bevaviour Tailscale Control Panel provides. **NOTE:** This is only active if you use ACLs + - Namespaces are now treated as Users + - All machines can communicate with all machines by default + - Tags should now work correctly and adding a host to Headscale should now reload the rules. + - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features + **0.13.0 (2022-xx-xx):** From d00251c63e3eb8c93c0ea21acda1040af5971331 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 21:24:02 +0100 Subject: [PATCH 17/38] fix(acls,machines): apply code review suggestions --- acls.go | 8 ++++---- acls_test.go | 2 +- machine.go | 37 ++++++++++++++++++++----------------- 3 files changed, 25 insertions(+), 22 deletions(-) diff --git a/acls.go b/acls.go index d5d39889..f9ed09da 100644 --- a/acls.go +++ b/acls.go @@ -204,7 +204,7 @@ func expandAlias( return ips, err } for _, n := range namespaces { - nodes := listMachinesInNamespace(machines, n) + nodes := filterMachinesByNamespace(machines, n) for _, node := range nodes { ips = append(ips, node.IPAddresses.ToStringSlice()...) } @@ -219,7 +219,7 @@ func expandAlias( return ips, err } for _, namespace := range owners { - machines := listMachinesInNamespace(machines, namespace) + machines := filterMachinesByNamespace(machines, namespace) for _, machine := range machines { if len(machine.HostInfo) == 0 { continue @@ -240,7 +240,7 @@ func expandAlias( } // if alias is a namespace - nodes := listMachinesInNamespace(machines, alias) + nodes := filterMachinesByNamespace(machines, alias) nodes, err := excludeCorrectlyTaggedNodes(aclPolicy, nodes, alias) if err != nil { return ips, err @@ -357,7 +357,7 @@ func expandPorts(portsStr string) (*[]tailcfg.PortRange, error) { return &ports, nil } -func listMachinesInNamespace(machines []Machine, namespace string) []Machine { +func filterMachinesByNamespace(machines []Machine, namespace string) []Machine { out := []Machine{} for _, machine := range machines { if machine.Namespace.Name == namespace { diff --git a/acls_test.go b/acls_test.go index e68a01f6..32dd5726 100644 --- a/acls_test.go +++ b/acls_test.go @@ -687,7 +687,7 @@ func Test_listMachinesInNamespace(t *testing.T) { } for _, test := range tests { t.Run(test.name, func(t *testing.T) { - if got := listMachinesInNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( + if got := filterMachinesByNamespace(test.args.machines, test.args.namespace); !reflect.DeepEqual( got, test.want, ) { diff --git a/machine.go b/machine.go index ba677f15..4c984d64 100644 --- a/machine.go +++ b/machine.go @@ -142,6 +142,16 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } +// matchSourceAndDestinationWithRule will check if source is authorized to communicate with destination through +// the given rule. +func matchSourceAndDestinationWithRule(rule tailcfg.FilterRule, source Machine, destination Machine) bool { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + return (containsAddresses(rule.SrcIPs, source.IPAddresses) && containsAddresses(dst, destination.IPAddresses)) || containsString(dst, "*") +} + // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -149,14 +159,12 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines := Machines{} - if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", - machine.MachineKey).Find(&machines).Error; err != nil { - log.Error().Err(err).Msg("Error accessing db") - + machines, err := h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") return Machines{}, err } - mMachines := make(map[uint64]Machine) + peers := make(map[uint64]Machine) // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. @@ -175,21 +183,16 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know // how to talk to node A and then add the peering resource. - for _, mchn := range machines { + for _, peer := range machines { for _, rule := range h.aclRules { - var dst []string - for _, d := range rule.DstPorts { - dst = append(dst, d.IP) - } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, mchn.IPAddresses) || containsString(dst, "*"))) || - (containsAddresses(rule.SrcIPs, mchn.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { - mMachines[mchn.ID] = mchn + if matchSourceAndDestinationWithRule(rule, *machine, peer) || matchSourceAndDestinationWithRule(rule, peer, *machine) { + peers[peer.ID] = peer } } } - authorizedMachines := make([]Machine, 0, len(mMachines)) - for _, m := range mMachines { + authorizedMachines := make([]Machine, 0, len(peers)) + for _, m := range peers { authorizedMachines = append(authorizedMachines, m) } sort.Slice( @@ -200,7 +203,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). - Msgf("Found some machines: %s", machines.String()) + Msgf("Found some machines: %v", machines) return authorizedMachines, nil } From 5e167cc00ad5aa312c1d0c50b289a5479d88b867 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:00:31 +0100 Subject: [PATCH 18/38] fix(tests): fix naming issues related to code review --- acls_test.go | 240 ++++++++++++++++++++++++++------------------------- 1 file changed, 123 insertions(+), 117 deletions(-) diff --git a/acls_test.go b/acls_test.go index 32dd5726..cb333090 100644 --- a/acls_test.go +++ b/acls_test.go @@ -99,16 +99,16 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) { // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. // the tag is matched in the Users section. func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", ) machine := Machine{ ID: 0, @@ -126,8 +126,8 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo", "foobar"}}, - TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + Groups: Groups{"group:test": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}}, ACLs: []ACL{ {Action: "accept", Users: []string{"tag:test"}, Ports: []string{"*:*"}}, }, @@ -143,20 +143,20 @@ func (s *Suite) TestValidExpandTagOwnersInUsers(c *check.C) { // match properly the IP's of the related hosts. The owner is valid and the tag is also valid. // the tag is matched in the Ports section. func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:test\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -170,8 +170,8 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - Groups: Groups{"group:test": []string{"foo", "foobar"}}, - TagOwners: TagOwners{"tag:test": []string{"bar", "group:test"}}, + Groups: Groups{"group:test": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"user3", "group:test"}}, ACLs: []ACL{ {Action: "accept", Users: []string{"*"}, Ports: []string{"tag:test:*"}}, }, @@ -187,20 +187,20 @@ func (s *Suite) TestValidExpandTagOwnersInPorts(c *check.C) { // tag on a host that isn't owned by a tag owners. So the namespace // of the host should be valid. func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "testmachine") + _, err = app.GetMachine("user1", "testmachine") c.Assert(err, check.NotNil) hostInfo := []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:foo\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"testmachine\",\"RequestTags\":[\"tag:foo\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -214,9 +214,9 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:test": []string{"user1"}}, ACLs: []ACL{ - {Action: "accept", Users: []string{"foo"}, Ports: []string{"*:*"}}, + {Action: "accept", Users: []string{"user1"}, Ports: []string{"*:*"}}, }, } err = app.UpdateACLRules() @@ -230,20 +230,20 @@ func (s *Suite) TestInvalidTagValidNamespace(c *check.C) { // an ACL rule is matching the tag to a namespace. It should not be valid since the // host should be tied to the tag now. func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { - namespace, err := app.CreateNamespace("foo") + namespace, err := app.CreateNamespace("user1") c.Assert(err, check.IsNil) pak, err := app.CreatePreAuthKey(namespace.Name, false, false, nil) c.Assert(err, check.IsNil) - _, err = app.GetMachine("foo", "webserver") + _, err = app.GetMachine("user1", "webserver") c.Assert(err, check.NotNil) hostInfo := []byte( "{\"OS\":\"centos\",\"Hostname\":\"webserver\",\"RequestTags\":[\"tag:webapp\"]}", ) machine := Machine{ ID: 1, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "webserver", @@ -255,12 +255,12 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { HostInfo: datatypes.JSON(hostInfo), } app.db.Save(&machine) - _, err = app.GetMachine("foo", "user") + _, err = app.GetMachine("user1", "user") hostInfo = []byte("{\"OS\":\"debian\",\"Hostname\":\"user\"}") c.Assert(err, check.NotNil) machine = Machine{ ID: 2, - MachineKey: "foo2", + MachineKey: "56789", NodeKey: "bar2", DiscoKey: "faab", Name: "user", @@ -274,11 +274,11 @@ func (s *Suite) TestValidTagInvalidNamespace(c *check.C) { app.db.Save(&machine) app.aclPolicy = &ACLPolicy{ - TagOwners: TagOwners{"tag:webapp": []string{"foo"}}, + TagOwners: TagOwners{"tag:webapp": []string{"user1"}}, ACLs: []ACL{ { Action: "accept", - Users: []string{"foo"}, + Users: []string{"user1"}, Ports: []string{"tag:webapp:80,443"}, }, }, @@ -339,7 +339,7 @@ func (s *Suite) TestPortNamespace(c *check.C) { ips, _ := app.getAvailableIPs() machine := Machine{ ID: 0, - MachineKey: "foo", + MachineKey: "12345", NodeKey: "bar", DiscoKey: "faa", Name: "testmachine", @@ -427,13 +427,13 @@ func Test_expandGroup(t *testing.T) { args: args{ aclPolicy: ACLPolicy{ Groups: Groups{ - "group:test": []string{"g1", "foo", "test"}, - "group:foo": []string{"foo", "test"}, + "group:test": []string{"user1", "user2", "user3"}, + "group:foo": []string{"user2", "user3"}, }, }, group: "group:test", }, - want: []string{"g1", "foo", "test"}, + want: []string{"user1", "user2", "user3"}, wantErr: false, }, { @@ -441,11 +441,11 @@ func Test_expandGroup(t *testing.T) { args: args{ aclPolicy: ACLPolicy{ Groups: Groups{ - "group:test": []string{"g1", "foo", "test"}, - "group:foo": []string{"foo", "test"}, + "group:test": []string{"user1", "user2", "user3"}, + "group:foo": []string{"user2", "user3"}, }, }, - group: "group:bar", + group: "group:undefined", }, want: []string{}, wantErr: true, @@ -478,45 +478,45 @@ func Test_expandTagOwners(t *testing.T) { wantErr bool }{ { - name: "simple tag", + name: "simple tag expansion", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"namespace1"}}, + TagOwners: TagOwners{"tag:test": []string{"user1"}}, }, tag: "tag:test", }, - want: []string{"namespace1"}, + want: []string{"user1"}, wantErr: false, }, { - name: "tag and group", + name: "expand with tag and group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"n1", "bar"}}, + Groups: Groups{"group:foo": []string{"user1", "user2"}}, TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, }, tag: "tag:test", }, - want: []string{"n1", "bar"}, + want: []string{"user1", "user2"}, wantErr: false, }, { - name: "namespace and group", + name: "expand with namespace and group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"n1", "bar"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + Groups: Groups{"group:foo": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "user3"}}, }, tag: "tag:test", }, - want: []string{"n1", "bar", "home"}, + want: []string{"user1", "user2", "user3"}, wantErr: false, }, { name: "invalid tag", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:foo": []string{"group:foo", "home"}}, + TagOwners: TagOwners{"tag:foo": []string{"group:foo", "user1"}}, }, tag: "tag:test", }, @@ -527,8 +527,8 @@ func Test_expandTagOwners(t *testing.T) { name: "invalid group", args: args{ aclPolicy: ACLPolicy{ - Groups: Groups{"group:bar": []string{"n1", "foo"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo", "home"}}, + Groups: Groups{"group:bar": []string{"user1", "user2"}}, + TagOwners: TagOwners{"tag:test": []string{"group:foo", "user2"}}, }, tag: "tag:test", }, @@ -647,40 +647,40 @@ func Test_listMachinesInNamespace(t *testing.T) { name: "1 machine in namespace", args: args{ machines: []Machine{ - {Namespace: Namespace{Name: "test"}}, + {Namespace: Namespace{Name: "joe"}}, }, - namespace: "test", + namespace: "joe", }, want: []Machine{ - {Namespace: Namespace{Name: "test"}}, + {Namespace: Namespace{Name: "joe"}}, }, }, { name: "3 machines, 2 in namespace", args: args{ machines: []Machine{ - {ID: 1, Namespace: Namespace{Name: "test"}}, - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 1, Namespace: Namespace{Name: "joe"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, }, - namespace: "foo", + namespace: "marc", }, want: []Machine{ - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, }, }, { name: "5 machines, 0 in namespace", args: args{ machines: []Machine{ - {ID: 1, Namespace: Namespace{Name: "test"}}, - {ID: 2, Namespace: Namespace{Name: "foo"}}, - {ID: 3, Namespace: Namespace{Name: "foo"}}, - {ID: 4, Namespace: Namespace{Name: "foo"}}, - {ID: 5, Namespace: Namespace{Name: "foo"}}, + {ID: 1, Namespace: Namespace{Name: "joe"}}, + {ID: 2, Namespace: Namespace{Name: "marc"}}, + {ID: 3, Namespace: Namespace{Name: "marc"}}, + {ID: 4, Namespace: Namespace{Name: "marc"}}, + {ID: 5, Namespace: Namespace{Name: "marc"}}, }, - namespace: "bar", + namespace: "mickael", }, want: []Machine{}, }, @@ -730,35 +730,35 @@ func Test_expandAlias(t *testing.T) { { name: "simple group", args: args{ - alias: "group:foo", + alias: "group:accountant", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, }, want: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, @@ -767,35 +767,35 @@ func Test_expandAlias(t *testing.T) { { name: "wrong group", args: args{ - alias: "group:test", + alias: "group:hr", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, }, }, want: []string{}, @@ -848,41 +848,41 @@ func Test_expandAlias(t *testing.T) { { name: "simple tag", args: args{ - alias: "tag:test", + alias: "tag:hr-webserver", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:hr-webserver": []string{"joe"}}, }, }, want: []string{"100.64.0.1", "100.64.0.2"}, @@ -891,36 +891,36 @@ func Test_expandAlias(t *testing.T) { { name: "No tag defined", args: args{ - alias: "tag:foo", + alias: "tag:hr-webserver", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "test"}, + Namespace: Namespace{Name: "mickael"}, }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:foo": []string{"foo", "bar"}}, - TagOwners: TagOwners{"tag:test": []string{"group:foo"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"group:accountant"}}, }, }, want: []string{}, @@ -929,41 +929,41 @@ func Test_expandAlias(t *testing.T) { { name: "list host in namespace without correctly tagged servers", args: args{ - alias: "foo", + alias: "joe", machines: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.3"), }, - Namespace: Namespace{Name: "bar"}, + Namespace: Namespace{Name: "marc"}, }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, }, want: []string{"100.64.0.4"}, @@ -1005,40 +1005,40 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { name: "exclude nodes with valid tags", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:test": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:accountant-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, - namespace: "foo", + namespace: "joe", }, want: []Machine{ { IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, wantErr: false, @@ -1047,54 +1047,60 @@ func Test_excludeCorrectlyTaggedNodes(t *testing.T) { name: "all nodes have invalid tags, don't exclude them", args: args{ aclPolicy: ACLPolicy{ - TagOwners: TagOwners{"tag:foo": []string{"foo"}}, + TagOwners: TagOwners{"tag:accountant-webserver": []string{"joe"}}, }, nodes: []Machine{ { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.1"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.2"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { IPAddresses: MachineAddresses{ netaddr.MustParseIP("100.64.0.4"), }, - Namespace: Namespace{Name: "foo"}, + Namespace: Namespace{Name: "joe"}, }, }, - namespace: "foo", + namespace: "joe", }, want: []Machine{ { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web1\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "joe"}, HostInfo: []byte( - "{\"OS\":\"centos\",\"Hostname\":\"foo\",\"RequestTags\":[\"tag:test\"]}", + "{\"OS\":\"centos\",\"Hostname\":\"hr-web2\",\"RequestTags\":[\"tag:hr-webserver\"]}", ), }, { - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.4")}, - Namespace: Namespace{Name: "foo"}, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.4"), + }, + Namespace: Namespace{Name: "joe"}, }, }, wantErr: false, From b3d0fb7a939ceabd4c1f7743149fe41329e29e7b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:47:04 +0100 Subject: [PATCH 19/38] fix(machine): revert modifications Using h.ListAllMachines also listed the current machine in the result. It's unnecessary (I don't know if it's harmful). Breaking the check with the `matchSourceAndDestinationWithRule` broke the tests. We have a specificity with the '*' destination that isn't symetrical. I need to think of a better way to do this. It too hard to read. --- machine.go | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/machine.go b/machine.go index 4c984d64..46f20daa 100644 --- a/machine.go +++ b/machine.go @@ -142,16 +142,6 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } -// matchSourceAndDestinationWithRule will check if source is authorized to communicate with destination through -// the given rule. -func matchSourceAndDestinationWithRule(rule tailcfg.FilterRule, source Machine, destination Machine) bool { - var dst []string - for _, d := range rule.DstPorts { - dst = append(dst, d.IP) - } - return (containsAddresses(rule.SrcIPs, source.IPAddresses) && containsAddresses(dst, destination.IPAddresses)) || containsString(dst, "*") -} - // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -159,9 +149,10 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines, err := h.ListAllMachines() - if err != nil { - log.Error().Err(err).Msg("Error retrieving list of machines") + machines := Machines{} + if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", + machine.MachineKey).Find(&machines).Error; err != nil { + log.Error().Err(err).Msg("Error accessing db") return Machines{}, err } peers := make(map[uint64]Machine) @@ -185,7 +176,13 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, peer := range machines { for _, rule := range h.aclRules { - if matchSourceAndDestinationWithRule(rule, *machine, peer) || matchSourceAndDestinationWithRule(rule, peer, *machine) { + var dst []string + for _, d := range rule.DstPorts { + dst = append(dst, d.IP) + } + if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, peer.IPAddresses) || containsString(dst, "*"))) || ( + // open return path + containsAddresses(rule.SrcIPs, peer.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { peers[peer.ID] = peer } } From 5242025ab3cc803c01932d7d903f747a8319913b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Sun, 20 Feb 2022 23:50:08 +0100 Subject: [PATCH 20/38] fix(machines): renaming following review comments --- machine.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/machine.go b/machine.go index 46f20daa..edebe031 100644 --- a/machine.go +++ b/machine.go @@ -188,13 +188,13 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { } } - authorizedMachines := make([]Machine, 0, len(peers)) + authorizedPeers := make([]Machine, 0, len(peers)) for _, m := range peers { - authorizedMachines = append(authorizedMachines, m) + authorizedPeers = append(authorizedPeers, m) } sort.Slice( - authorizedMachines, - func(i, j int) bool { return authorizedMachines[i].ID < authorizedMachines[j].ID }, + authorizedPeers, + func(i, j int) bool { return authorizedPeers[i].ID < authorizedPeers[j].ID }, ) log.Trace(). @@ -202,7 +202,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msgf("Found some machines: %v", machines) - return authorizedMachines, nil + return authorizedPeers, nil } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { From 960412a335729869b063b7101ece86367f35c882 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:02:27 +0100 Subject: [PATCH 21/38] fix(machines): simplify complex if check This should fix the performance issue with computation of `dst` variable. It's also easier to read now. --- machine.go | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/machine.go b/machine.go index edebe031..45434075 100644 --- a/machine.go +++ b/machine.go @@ -132,8 +132,8 @@ func (h *Headscale) ListAllMachines() ([]Machine, error) { return machines, nil } -func containsAddresses(inputs []string, addrs MachineAddresses) bool { - for _, addr := range addrs.ToStringSlice() { +func containsAddresses(inputs []string, addrs []string) bool { + for _, addr := range addrs { if containsString(inputs, addr) { return true } @@ -142,6 +142,11 @@ func containsAddresses(inputs []string, addrs MachineAddresses) bool { return false } +// matchSourceAndDestinationWithRule +func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { + return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) +} + // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { log.Trace(). @@ -180,9 +185,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if (containsAddresses(rule.SrcIPs, machine.IPAddresses) && (containsAddresses(dst, peer.IPAddresses) || containsString(dst, "*"))) || ( - // open return path - containsAddresses(rule.SrcIPs, peer.IPAddresses) && containsAddresses(dst, machine.IPAddresses)) { + if matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice()) || // match source and destination + matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination + matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path peers[peer.ID] = peer } } From 9c6ce02554020ae114089eecc5e431c0d36dffe4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:05:04 +0100 Subject: [PATCH 22/38] fix(machines): use ListAllMachines function added a simple filter to remove the current node --- machine.go | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/machine.go b/machine.go index 45434075..8a33e1d8 100644 --- a/machine.go +++ b/machine.go @@ -154,10 +154,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines := Machines{} - if err := h.db.Preload("Namespace").Where("machine_key <> ? AND registered", - machine.MachineKey).Find(&machines).Error; err != nil { - log.Error().Err(err).Msg("Error accessing db") + machines, err := h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") return Machines{}, err } peers := make(map[uint64]Machine) @@ -180,6 +179,9 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { // how to talk to node A and then add the peering resource. for _, peer := range machines { + if peer.ID == machine.ID { + continue + } for _, rule := range h.aclRules { var dst []string for _, d := range rule.DstPorts { From f0068601364890852fde36a425299608ec82cca7 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:15:34 +0100 Subject: [PATCH 23/38] feat(machines): untie dependency with class for filter func The dependency to the `headscale` struct makes tests harder to do. This change allow to easily add some tests for this quite sensible function. --- machine.go | 19 ++++++++++--------- machine_test.go | 7 +++++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/machine.go b/machine.go index 8a33e1d8..30c4ad92 100644 --- a/machine.go +++ b/machine.go @@ -148,19 +148,13 @@ func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations [] } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { +func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) (Machines, error) { log.Trace(). Caller(). Str("machine", machine.Name). Msg("Finding peers filtered by ACLs") - machines, err := h.ListAllMachines() - if err != nil { - log.Error().Err(err).Msg("Error retrieving list of machines") - return Machines{}, err - } peers := make(map[uint64]Machine) - // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. @@ -182,7 +176,7 @@ func (h *Headscale) getFilteredByACLPeers(machine *Machine) (Machines, error) { if peer.ID == machine.ID { continue } - for _, rule := range h.aclRules { + for _, rule := range rules { var dst []string for _, d := range rule.DstPorts { dst = append(dst, d.IP) @@ -301,10 +295,17 @@ func (h *Headscale) getSharedTo(machine *Machine) (Machines, error) { func (h *Headscale) getPeers(machine *Machine) (Machines, error) { var peers Machines var err error + // If ACLs rules are defined, filter visible host list with the ACLs // else use the classic namespace scope if h.aclPolicy != nil { - peers, err = h.getFilteredByACLPeers(machine) + var machines []Machine + machines, err = h.ListAllMachines() + if err != nil { + log.Error().Err(err).Msg("Error retrieving list of machines") + return Machines{}, err + } + peers, err = getFilteredByACLPeers(machines, h.aclRules, machine) if err != nil { log.Error(). Caller(). diff --git a/machine_test.go b/machine_test.go index f9e58be9..90caf9d2 100644 --- a/machine_test.go +++ b/machine_test.go @@ -219,10 +219,13 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { _, err = testMachine.GetHostInfo() c.Assert(err, check.IsNil) - peersOfTestMachine, err := app.getFilteredByACLPeers(testMachine) + machines, err := app.ListAllMachines() c.Assert(err, check.IsNil) - peersOfAdminMachine, err := app.getFilteredByACLPeers(adminMachine) + peersOfTestMachine, err := getFilteredByACLPeers(machines, app.aclRules, testMachine) + c.Assert(err, check.IsNil) + + peersOfAdminMachine, err := getFilteredByACLPeers(machines, app.aclRules, adminMachine) c.Assert(err, check.IsNil) c.Log(peersOfTestMachine) From 5ab62378aef28cfadf0739b891b0cd7b38d8c033 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 09:57:31 +0100 Subject: [PATCH 24/38] tests(machines): test all combinations of peer filtering --- machine_test.go | 168 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) diff --git a/machine_test.go b/machine_test.go index 90caf9d2..fb104f7d 100644 --- a/machine_test.go +++ b/machine_test.go @@ -2,11 +2,14 @@ package headscale import ( "fmt" + "reflect" "strconv" + "testing" "time" "gopkg.in/check.v1" "inet.af/netaddr" + "tailscale.com/tailcfg" ) func (s *Suite) TestGetMachine(c *check.C) { @@ -295,3 +298,168 @@ func (s *Suite) TestSerdeAddressStrignSlice(c *check.C) { c.Assert(deserialized[i], check.Equals, input[i]) } } + +func Test_getFilteredByACLPeers(t *testing.T) { + type args struct { + machines []Machine + rules []tailcfg.FilterRule + machine *Machine + } + tests := []struct { + name string + args args + want Machines + wantErr bool + }{ + { + name: "all hosts can talk to each other", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "*"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + }, + want: Machines{ + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + wantErr: false, + }, + { + name: "One host can talk to another, but not all hosts", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + }, + want: Machines{ + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + wantErr: false, + }, + { + name: "host cannot directly talk to destination, but return path is authorized", + args: args{ + machines: []Machine{ // list of all machines in the database + { + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, + Namespace: Namespace{Name: "joe"}, + }, + { + ID: 2, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + rules: []tailcfg.FilterRule{ // list of all ACLRules registered + {SrcIPs: []string{"100.64.0.3"}, + DstPorts: []tailcfg.NetPortRange{ + {IP: "100.64.0.2"}, + }, + }, + }, + machine: &Machine{ // current machine + ID: 1, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, + Namespace: Namespace{Name: "marc"}, + }, + }, + want: Machines{ + { + ID: 3, + IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, + Namespace: Namespace{Name: "mickael"}, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) + if (err != nil) != tt.wantErr { + t.Errorf("getFilteredByACLPeers() error = %v, wantErr %v", err, tt.wantErr) + return + } + if !reflect.DeepEqual(got, tt.want) { + t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) + } + }) + } +} + +var getFilteredByACLPeersTestRules = []tailcfg.FilterRule{ + { + SrcIPs: []string{"100.64.0.1"}, + DstPorts: []tailcfg.NetPortRange{{IP: "*"}}, + }, +} From 4bbe0051f6410b934b4585a4d690d442cbb21791 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 10:02:59 +0100 Subject: [PATCH 25/38] chore(machines): apply lint --- machine.go | 15 ++++----------- machine_test.go | 39 ++++++++++++--------------------------- 2 files changed, 16 insertions(+), 38 deletions(-) diff --git a/machine.go b/machine.go index 30c4ad92..0ec7b814 100644 --- a/machine.go +++ b/machine.go @@ -142,13 +142,13 @@ func containsAddresses(inputs []string, addrs []string) bool { return false } -// matchSourceAndDestinationWithRule +// matchSourceAndDestinationWithRule. func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) (Machines, error) { +func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) Machines { log.Trace(). Caller(). Str("machine", machine.Name). @@ -203,7 +203,7 @@ func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machi Str("machine", machine.Name). Msgf("Found some machines: %v", machines) - return authorizedPeers, nil + return authorizedPeers } func (h *Headscale) getDirectPeers(machine *Machine) (Machines, error) { @@ -303,17 +303,10 @@ func (h *Headscale) getPeers(machine *Machine) (Machines, error) { machines, err = h.ListAllMachines() if err != nil { log.Error().Err(err).Msg("Error retrieving list of machines") - return Machines{}, err - } - peers, err = getFilteredByACLPeers(machines, h.aclRules, machine) - if err != nil { - log.Error(). - Caller(). - Err(err). - Msg("Cannot fetch peers") return Machines{}, err } + peers = getFilteredByACLPeers(machines, h.aclRules, machine) } else { direct, err := h.getDirectPeers(machine) if err != nil { diff --git a/machine_test.go b/machine_test.go index fb104f7d..3be3332b 100644 --- a/machine_test.go +++ b/machine_test.go @@ -225,11 +225,8 @@ func (s *Suite) TestGetACLFilteredPeers(c *check.C) { machines, err := app.ListAllMachines() c.Assert(err, check.IsNil) - peersOfTestMachine, err := getFilteredByACLPeers(machines, app.aclRules, testMachine) - c.Assert(err, check.IsNil) - - peersOfAdminMachine, err := getFilteredByACLPeers(machines, app.aclRules, adminMachine) - c.Assert(err, check.IsNil) + peersOfTestMachine := getFilteredByACLPeers(machines, app.aclRules, testMachine) + peersOfAdminMachine := getFilteredByACLPeers(machines, app.aclRules, adminMachine) c.Log(peersOfTestMachine) c.Assert(len(peersOfTestMachine), check.Equals, 4) @@ -306,10 +303,9 @@ func Test_getFilteredByACLPeers(t *testing.T) { machine *Machine } tests := []struct { - name string - args args - want Machines - wantErr bool + name string + args args + want Machines }{ { name: "all hosts can talk to each other", @@ -332,7 +328,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "*"}, }, @@ -356,7 +353,6 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "mickael"}, }, }, - wantErr: false, }, { name: "One host can talk to another, but not all hosts", @@ -379,7 +375,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.1", "100.64.0.2", "100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "100.64.0.2"}, }, @@ -398,7 +395,6 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "marc"}, }, }, - wantErr: false, }, { name: "host cannot directly talk to destination, but return path is authorized", @@ -421,7 +417,8 @@ func Test_getFilteredByACLPeers(t *testing.T) { }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered - {SrcIPs: []string{"100.64.0.3"}, + { + SrcIPs: []string{"100.64.0.3"}, DstPorts: []tailcfg.NetPortRange{ {IP: "100.64.0.2"}, }, @@ -440,26 +437,14 @@ func Test_getFilteredByACLPeers(t *testing.T) { Namespace: Namespace{Name: "mickael"}, }, }, - wantErr: false, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got, err := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) - if (err != nil) != tt.wantErr { - t.Errorf("getFilteredByACLPeers() error = %v, wantErr %v", err, tt.wantErr) - return - } + got := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) if !reflect.DeepEqual(got, tt.want) { t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) } }) } } - -var getFilteredByACLPeersTestRules = []tailcfg.FilterRule{ - { - SrcIPs: []string{"100.64.0.1"}, - DstPorts: []tailcfg.NetPortRange{{IP: "*"}}, - }, -} From 25550f886663c35c4a5c063f31ba93ef6beef89c Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 16:06:20 +0100 Subject: [PATCH 26/38] chore(format): run prettier on repo --- CHANGELOG.md | 8 ++--- acls_test.go | 6 ++-- machine.go | 23 ++++++++++++--- machine_test.go | 78 +++++++++++++++++++++++++++++++------------------ 4 files changed, 77 insertions(+), 38 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7cf99d9f..6c04a170 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,9 +5,9 @@ **0.14.0 (2022-xx-xx):** **UPCOMING BREAKING**: -From the **next** version (`0.15.0`), all machines will be able to communicate regardless of -if they are in the same namespace. This means that the behaviour currently limited to ACLs -will become default. From version `0.15.0`, all limitation of communications must be done +From the **next** version (`0.15.0`), all machines will be able to communicate regardless of +if they are in the same namespace. This means that the behaviour currently limited to ACLs +will become default. From version `0.15.0`, all limitation of communications must be done with ACLs. This is a part of aligning `headscale`'s behaviour with Tailscale's upstream behaviour. @@ -17,7 +17,7 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - ACLs have been rewritten to align with the bevaviour Tailscale Control Panel provides. **NOTE:** This is only active if you use ACLs - Namespaces are now treated as Users - All machines can communicate with all machines by default - - Tags should now work correctly and adding a host to Headscale should now reload the rules. + - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features **0.13.0 (2022-02-18):** diff --git a/acls_test.go b/acls_test.go index cb333090..44eb2e15 100644 --- a/acls_test.go +++ b/acls_test.go @@ -919,8 +919,10 @@ func Test_expandAlias(t *testing.T) { }, }, aclPolicy: ACLPolicy{ - Groups: Groups{"group:accountant": []string{"joe", "marc"}}, - TagOwners: TagOwners{"tag:accountant-webserver": []string{"group:accountant"}}, + Groups: Groups{"group:accountant": []string{"joe", "marc"}}, + TagOwners: TagOwners{ + "tag:accountant-webserver": []string{"group:accountant"}, + }, }, }, want: []string{}, diff --git a/machine.go b/machine.go index 0ec7b814..b1dd0d27 100644 --- a/machine.go +++ b/machine.go @@ -143,12 +143,22 @@ func containsAddresses(inputs []string, addrs []string) bool { } // matchSourceAndDestinationWithRule. -func matchSourceAndDestinationWithRule(ruleSources []string, ruleDestinations []string, source []string, destination []string) bool { - return containsAddresses(ruleSources, source) && containsAddresses(ruleDestinations, destination) +func matchSourceAndDestinationWithRule( + ruleSources []string, + ruleDestinations []string, + source []string, + destination []string, +) bool { + return containsAddresses(ruleSources, source) && + containsAddresses(ruleDestinations, destination) } // getFilteredByACLPeerss should return the list of peers authorized to be accessed from machine. -func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machine *Machine) Machines { +func getFilteredByACLPeers( + machines []Machine, + rules []tailcfg.FilterRule, + machine *Machine, +) Machines { log.Trace(). Caller(). Str("machine", machine.Name). @@ -181,7 +191,12 @@ func getFilteredByACLPeers(machines []Machine, rules []tailcfg.FilterRule, machi for _, d := range rule.DstPorts { dst = append(dst, d.IP) } - if matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice()) || // match source and destination + if matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + machine.IPAddresses.ToStringSlice(), + peer.IPAddresses.ToStringSlice(), + ) || // match source and destination matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path peers[peer.ID] = peer diff --git a/machine_test.go b/machine_test.go index 3be3332b..b1cd3419 100644 --- a/machine_test.go +++ b/machine_test.go @@ -312,19 +312,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -359,19 +365,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -401,19 +413,25 @@ func Test_getFilteredByACLPeers(t *testing.T) { args: args{ machines: []Machine{ // list of all machines in the database { - ID: 1, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.1")}, - Namespace: Namespace{Name: "joe"}, + ID: 1, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.1"), + }, + Namespace: Namespace{Name: "joe"}, }, { - ID: 2, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.2")}, - Namespace: Namespace{Name: "marc"}, + ID: 2, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.2"), + }, + Namespace: Namespace{Name: "marc"}, }, { - ID: 3, - IPAddresses: MachineAddresses{netaddr.MustParseIP("100.64.0.3")}, - Namespace: Namespace{Name: "mickael"}, + ID: 3, + IPAddresses: MachineAddresses{ + netaddr.MustParseIP("100.64.0.3"), + }, + Namespace: Namespace{Name: "mickael"}, }, }, rules: []tailcfg.FilterRule{ // list of all ACLRules registered @@ -441,7 +459,11 @@ func Test_getFilteredByACLPeers(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := getFilteredByACLPeers(tt.args.machines, tt.args.rules, tt.args.machine) + got := getFilteredByACLPeers( + tt.args.machines, + tt.args.rules, + tt.args.machine, + ) if !reflect.DeepEqual(got, tt.want) { t.Errorf("getFilteredByACLPeers() = %v, want %v", got, tt.want) } From 211fe4034a0b32cc1c86c60370a744642ad2e5d1 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 16:10:20 +0100 Subject: [PATCH 27/38] chore(linter): ignore tt var as it's generated code (vscode) --- .golangci.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/.golangci.yaml b/.golangci.yaml index 965f5496..153cd7c3 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -48,6 +48,7 @@ linters-settings: - ip - ok - c + - tt gocritic: disabled-checks: From 50af44bc2fa7a578b3e141518ffcef2e32976325 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 20:06:31 +0100 Subject: [PATCH 28/38] fix: add error checking in acl and poll If aclPolicy is not defined, in updateAclPolicy, return an error. --- acls.go | 4 ++++ poll.go | 17 +++++++++-------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/acls.go b/acls.go index f9ed09da..db2fc588 100644 --- a/acls.go +++ b/acls.go @@ -86,6 +86,10 @@ func (h *Headscale) UpdateACLRules() error { func (h *Headscale) generateACLRules() ([]tailcfg.FilterRule, error) { rules := []tailcfg.FilterRule{} + if h.aclPolicy == nil { + return nil, errEmptyPolicy + } + machines, err := h.ListAllMachines() if err != nil { return nil, err diff --git a/poll.go b/poll.go index 96db43f2..21aa3b33 100644 --- a/poll.go +++ b/poll.go @@ -95,15 +95,16 @@ func (h *Headscale) PollNetMapHandler(ctx *gin.Context) { now := time.Now().UTC() // update ACLRules with peer informations (to update server tags if necessary) - err = h.UpdateACLRules() - if err != nil { - log.Error(). - Caller(). - Str("func", "handleAuthKey"). - Str("machine", machine.Name). - Err(err) + if h.aclPolicy != nil { + err = h.UpdateACLRules() + if err != nil { + log.Error(). + Caller(). + Str("func", "handleAuthKey"). + Str("machine", machine.Name). + Err(err) + } } - // From Tailscale client: // // ReadOnly is whether the client just wants to fetch the MapResponse, From baae266db015297ff304c1547fec6eed2fc6c45b Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 20:25:41 +0100 Subject: [PATCH 29/38] Update acls_test.go Co-authored-by: Kristoffer Dalby --- acls_test.go | 1 + 1 file changed, 1 insertion(+) diff --git a/acls_test.go b/acls_test.go index 44eb2e15..965c0076 100644 --- a/acls_test.go +++ b/acls_test.go @@ -59,6 +59,7 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } +# TODO(kradalby): Make tests values safe, independent and descriptive. func (s *Suite) TestInvalidAction(c *check.C) { app.aclPolicy = &ACLPolicy{ ACLs: []ACL{ From 650108c7c7fc7fdf84cd5cd2fbe6be043ef74dd9 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 21:45:15 +0100 Subject: [PATCH 30/38] chore(fmt): apply fmt --- machine.go | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/machine.go b/machine.go index b1dd0d27..ee483422 100644 --- a/machine.go +++ b/machine.go @@ -197,8 +197,18 @@ func getFilteredByACLPeers( machine.IPAddresses.ToStringSlice(), peer.IPAddresses.ToStringSlice(), ) || // match source and destination - matchSourceAndDestinationWithRule(rule.SrcIPs, dst, machine.IPAddresses.ToStringSlice(), []string{"*"}) || // match source and all destination - matchSourceAndDestinationWithRule(rule.SrcIPs, dst, peer.IPAddresses.ToStringSlice(), machine.IPAddresses.ToStringSlice()) { // match return path + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + machine.IPAddresses.ToStringSlice(), + []string{"*"}, + ) || // match source and all destination + matchSourceAndDestinationWithRule( + rule.SrcIPs, + dst, + peer.IPAddresses.ToStringSlice(), + machine.IPAddresses.ToStringSlice(), + ) { // match return path peers[peer.ID] = peer } } From d971f0f0e62ec3ca3cf58f236db62fa9d09405a4 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Mon, 21 Feb 2022 21:48:05 +0100 Subject: [PATCH 31/38] fix(acls_test): fix comment in go code --- acls_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/acls_test.go b/acls_test.go index 965c0076..5534257d 100644 --- a/acls_test.go +++ b/acls_test.go @@ -59,7 +59,7 @@ func (s *Suite) TestBasicRule(c *check.C) { c.Assert(rules, check.NotNil) } -# TODO(kradalby): Make tests values safe, independent and descriptive. +// TODO(kradalby): Make tests values safe, independent and descriptive. func (s *Suite) TestInvalidAction(c *check.C) { app.aclPolicy = &ACLPolicy{ ACLs: []ACL{ From bbadeb567aa2c767e0ada229e4ce05b164316f42 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 21 Feb 2022 21:41:48 +0000 Subject: [PATCH 32/38] docs(README): update contributors --- README.md | 45 ++++++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e7ba6649..071dd2bd 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,13 @@ make build ohdearaugustin + + + Adrien +
+ Adrien Raffin-Caboisse +
+ Alessandro @@ -157,6 +164,8 @@ make build Alessandro (Ale) Segala + + unreality/ @@ -164,8 +173,6 @@ make build unreality - - Eugen @@ -201,6 +208,8 @@ make build Michael G. + + Paul @@ -208,8 +217,6 @@ make build Paul Tötterman - - Casey @@ -245,6 +252,8 @@ make build thomas + + Abraham @@ -252,15 +261,6 @@ make build Abraham Ingersoll - - - - - Adrien -
- Adrien Raffin-Caboisse -
- Artem @@ -305,6 +305,13 @@ make build JJGadgets + + + Jamie +
+ Jamie Greeff +
+ Jim @@ -333,6 +340,8 @@ make build Ryan Fowler + + Shaanan @@ -340,8 +349,6 @@ make build Shaanan Cohney - - Tanner/ @@ -377,6 +384,8 @@ make build Tjerk Woudsma + + Zakhar @@ -384,8 +393,6 @@ make build Zakhar Bessarab - - ZiYuan/ @@ -421,6 +428,8 @@ make build lion24 + + Wakeful-Cloud/ @@ -428,8 +437,6 @@ make build Wakeful-Cloud - - zy/ From f2f8d834e81bd1818e7f96a9446b356276927164 Mon Sep 17 00:00:00 2001 From: Adrien Raffin-Caboisse Date: Tue, 22 Feb 2022 11:26:21 +0100 Subject: [PATCH 33/38] fix(machine): remove comment After some more tests in tailscale I couldn't replicate the behavior described in there. When adding a rule, allowing A to talk to B the reverse connection was instantly added to B to allow communication to B. The previous assumption was probably wrong. --- machine.go | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/machine.go b/machine.go index ee483422..3c704ad3 100644 --- a/machine.go +++ b/machine.go @@ -167,21 +167,6 @@ func getFilteredByACLPeers( peers := make(map[uint64]Machine) // Aclfilter peers here. We are itering through machines in all namespaces and search through the computed aclRules // for match between rule SrcIPs and DstPorts. If the rule is a match we allow the machine to be viewable. - - // FIXME: On official control plane if a rule allow user A to talk to user B but NO rule allows user B to talk to - // user A. The behaviour is the following - // - // On official tailscale control plane: - // on first `tailscale status`` on node A we can see node B. The `tailscale status` command on node B doesn't show node A - // We can successfully establish a communication from A to B. When it's done, if we run the `tailscale status` command - // on node B again we can now see node A. It's not possible to establish a communication from node B to node A. - // On this implementation of the feature - // on any `tailscale status` command on node A we can see node B. The `tailscale status` command on node B DOES show A. - // - // I couldn't find a way to not clutter the output of `tailscale status` with all nodes that we could be talking to. - // In order to do this we would need to be able to identify that node A want to talk to node B but that Node B doesn't know - // how to talk to node A and then add the peering resource. - for _, peer := range machines { if peer.ID == machine.ID { continue From bfbcea35a03fc7cd80a46a8b5a0c9b1fee5a1e24 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 16:18:25 +0000 Subject: [PATCH 34/38] Remove dependency on CGO This commit changes the SQLite dependency to one that does not depend on CGO. It uses a C-to-Go translated sqlite library that is Pure go. --- .goreleaser.yml | 27 +-- CHANGELOG.md | 4 + Dockerfile | 2 +- Dockerfile.alpine | 2 +- Dockerfile.debug | 2 +- Makefile | 2 +- db.go | 2 +- go.mod | 21 ++- go.sum | 428 +++++++++++++++++----------------------------- 9 files changed, 192 insertions(+), 298 deletions(-) diff --git a/.goreleaser.yml b/.goreleaser.yml index d1dec26f..bd517d9f 100644 --- a/.goreleaser.yml +++ b/.goreleaser.yml @@ -10,15 +10,12 @@ builds: - id: darwin-amd64 main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - darwin goarch: - amd64 - env: - - PKG_CONFIG_SYSROOT_DIR=/sysroot/macos/amd64 - - PKG_CONFIG_PATH=/sysroot/macos/amd64/usr/local/lib/pkgconfig - - CC=o64-clang - - CXX=o64-clang++ flags: - -mod=readonly ldflags: @@ -27,46 +24,40 @@ builds: - id: linux-armhf main: ./cmd/headscale/headscale.go mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm goarm: - "7" - env: - - CC=arm-linux-gnueabihf-gcc - - CXX=arm-linux-gnueabihf-g++ - - CGO_FLAGS=--sysroot=/sysroot/linux/armhf - - CGO_LDFLAGS=--sysroot=/sysroot/linux/armhf - - PKG_CONFIG_SYSROOT_DIR=/sysroot/linux/armhf - - PKG_CONFIG_PATH=/sysroot/linux/armhf/opt/vc/lib/pkgconfig:/sysroot/linux/armhf/usr/lib/arm-linux-gnueabihf/pkgconfig:/sysroot/linux/armhf/usr/lib/pkgconfig:/sysroot/linux/armhf/usr/local/lib/pkgconfig flags: - -mod=readonly ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-amd64 + mod_timestamp: "{{ .CommitTimestamp }}" env: - - CGO_ENABLED=1 + - CGO_ENABLED=0 goos: - linux goarch: - amd64 main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} - id: linux-arm64 + mod_timestamp: "{{ .CommitTimestamp }}" + env: + - CGO_ENABLED=0 goos: - linux goarch: - arm64 - env: - - CGO_ENABLED=1 - - CC=aarch64-linux-gnu-gcc main: ./cmd/headscale/headscale.go - mod_timestamp: "{{ .CommitTimestamp }}" ldflags: - -s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=v{{.Version}} diff --git a/CHANGELOG.md b/CHANGELOG.md index 6c04a170..06a0ec62 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,6 +20,10 @@ This is a part of aligning `headscale`'s behaviour with Tailscale's upstream beh - Tags should now work correctly and adding a host to Headscale should now reload the rules. - The documentation have a [fictional example](docs/acls.md) that should cover some use cases of the ACLs features +**Changes**: + +- Remove dependency on CGO (switch from CGO SQLite to pure Go) [#346](https://github.com/juanfont/headscale/pull/346) + **0.13.0 (2022-02-18):** **Features**: diff --git a/Dockerfile b/Dockerfile index 6e577753..86f5bd4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.alpine b/Dockerfile.alpine index b07e1904..af884344 100644 --- a/Dockerfile.alpine +++ b/Dockerfile.alpine @@ -9,7 +9,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN strip /go/bin/headscale RUN test -e /go/bin/headscale diff --git a/Dockerfile.debug b/Dockerfile.debug index 3d2675f9..38385cef 100644 --- a/Dockerfile.debug +++ b/Dockerfile.debug @@ -8,7 +8,7 @@ RUN go mod download COPY . . -RUN go install -a -ldflags="-extldflags=-static" -tags netgo,sqlite_omit_load_extension ./cmd/headscale +RUN GGO_ENABLED=0 GOOS=linux go install -a ./cmd/headscale RUN test -e /go/bin/headscale # Debug image diff --git a/Makefile b/Makefile index 69935bc0..52145090 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ PROTO_SOURCES = $(call rwildcard,,*.proto) build: - go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go + GGO_ENABLED=0 go build -ldflags "-s -w -X github.com/juanfont/headscale/cmd/headscale/cli.Version=$(version)" cmd/headscale/headscale.go dev: lint test build diff --git a/db.go b/db.go index 1b53dc88..7aadd20a 100644 --- a/db.go +++ b/db.go @@ -3,8 +3,8 @@ package headscale import ( "errors" + "github.com/glebarez/sqlite" "gorm.io/driver/postgres" - "gorm.io/driver/sqlite" "gorm.io/gorm" "gorm.io/gorm/logger" ) diff --git a/go.mod b/go.mod index bbba4646..8b721fa7 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,7 @@ require ( github.com/efekarakus/termcolor v1.0.1 github.com/fatih/set v0.2.1 github.com/gin-gonic/gin v1.7.7 + github.com/glebarez/sqlite v1.3.5 github.com/gofrs/uuid v4.2.0+incompatible github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 @@ -19,14 +20,13 @@ require ( github.com/prometheus/client_golang v1.12.1 github.com/pterm/pterm v0.12.36 github.com/rs/zerolog v1.26.1 - github.com/soheilhy/cmux v0.1.5 github.com/spf13/cobra v1.3.0 github.com/spf13/viper v1.10.1 github.com/stretchr/testify v1.7.0 github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e github.com/zsais/go-gin-prometheus v0.1.0 - golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 + golang.org/x/crypto v0.0.0-20220214200702-86341886e292 golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 @@ -36,9 +36,8 @@ require ( gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c gopkg.in/yaml.v2 v2.4.0 gorm.io/datatypes v1.0.5 - gorm.io/driver/postgres v1.2.3 - gorm.io/driver/sqlite v1.2.6 - gorm.io/gorm v1.22.5 + gorm.io/driver/postgres v1.3.1 + gorm.io/gorm v1.23.1 inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 tailscale.com v1.20.4 ) @@ -58,8 +57,8 @@ require ( github.com/docker/go-connections v0.4.0 // indirect github.com/docker/go-units v0.4.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/gin-contrib/sse v0.1.0 // indirect + github.com/glebarez/go-sqlite v1.14.7 // indirect github.com/go-playground/locales v0.14.0 // indirect github.com/go-playground/universal-translator v0.18.0 // indirect github.com/go-playground/validator/v10 v10.10.0 // indirect @@ -70,6 +69,7 @@ require ( github.com/google/go-github v17.0.0+incompatible // indirect github.com/google/go-querystring v1.1.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect + github.com/google/uuid v1.3.0 // indirect github.com/gookit/color v1.5.0 // indirect github.com/hashicorp/go-version v1.4.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect @@ -112,6 +112,7 @@ require ( github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect + github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect github.com/rivo/uniseg v0.2.0 // indirect github.com/rogpeppe/go-internal v1.8.1 // indirect github.com/sirupsen/logrus v1.8.1 // indirect @@ -136,6 +137,12 @@ require ( gopkg.in/ini.v1 v1.66.4 // indirect gopkg.in/square/go-jose.v2 v2.6.0 // indirect gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect - gorm.io/driver/mysql v1.2.3 // indirect + gorm.io/driver/mysql v1.3.2 // indirect + gorm.io/driver/sqlite v1.3.1 // indirect + gorm.io/driver/sqlserver v1.3.1 // indirect + modernc.org/libc v1.14.3 // indirect + modernc.org/mathutil v1.4.1 // indirect + modernc.org/memory v1.0.5 // indirect + modernc.org/sqlite v1.14.5 // indirect sigs.k8s.io/yaml v1.3.0 // indirect ) diff --git a/go.sum b/go.sum index 28145899..20eec3f4 100644 --- a/go.sum +++ b/go.sum @@ -1,4 +1,3 @@ -bazil.org/fuse v0.0.0-20160811212531-371fbbdaa898/go.mod h1:Xbm+BRKSBEpa4q4hTSxohYNQpsxXPbPry4JJWOB3LB8= bazil.org/fuse v0.0.0-20200407214033-5883e5a4b512/go.mod h1:FbcW6z/2VytnFDhZfumh8Ss8zxHE6qpMP5sHTRe0EaM= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= @@ -40,7 +39,6 @@ cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM7 cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk= -cloud.google.com/go/firestore v1.6.0/go.mod h1:afJwI0vaXwAG54kI7A//lP/lSPDkQORQuMkv56TxEPU= cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= @@ -56,6 +54,9 @@ contrib.go.opencensus.io/exporter/ocagent v0.7.0/go.mod h1:IshRmMJBhDfFj5Y67nVhM dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= github.com/AlecAivazis/survey/v2 v2.3.2 h1:TqTB+aDDCLYhf9/bD2TwSO8u8jDSmMUd2SUVO4gCnU8= github.com/AlecAivazis/survey/v2 v2.3.2/go.mod h1:TH2kPCDU3Kqq7pLbnCWwZXDBjnhZtmsCle5EiYDJ2fg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v0.19.0/go.mod h1:h6H6c8enJmmocHUbLiiGY6sx7f9i+X3m1CHdd5c6Rdw= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v0.11.0/go.mod h1:HcM1YX14R7CJcghJGOYCgdezslRSVzqwLf/q+4Y2r/0= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2TzfVZ1pCb5vxm4BtZPUdYWe/Xo8= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8= github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= @@ -63,9 +64,7 @@ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03 github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ= -github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= -github.com/MarvinJWendt/testza v0.2.1 h1:eitywm1lzygA2KCyn55jFVdOaXj5I9LeOsLNeifd2Kw= github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= @@ -74,7 +73,6 @@ github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzX github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= -github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.5.1 h1:aPJp2QD7OOrhO5tQXqQoGSJc+DjDtWTGLOmNyAm6FgY= github.com/Microsoft/go-winio v0.5.1/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= github.com/Netflix/go-expect v0.0.0-20180615182759-c93bf25de8e8 h1:xzYJEypr/85nBpB11F9br+3HUrpgb+fcm5iADzXXYEw= @@ -83,10 +81,6 @@ github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5 h1:TngWCqHvy9oXAN6lEV github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc= -github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= -github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= -github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= -github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -94,20 +88,14 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk541a8SKzHPHnH3zbiI+7dagKZ0cgpgrD7Fyho= github.com/andybalholm/cascadia v1.1.0/go.mod h1:GsXiBklL0woXo1j/WYWtSYYC4ouU9PqHO0sqidkEA4Y= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= -github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= -github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= github.com/atomicgo/cursor v0.0.1 h1:xdogsqa6YYlLfM+GyClC/Lchf7aiMerFiZQn7soTOoU= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= -github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= -github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -116,18 +104,11 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM= github.com/bufbuild/buf v0.37.0/go.mod h1:lQ1m2HkIaGOFba6w/aC3KYBHhKEOESP3gaAEpS3dAFM= -github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= -github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= -github.com/cenkalti/backoff/v4 v4.1.0/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= -github.com/cenkalti/backoff/v4 v4.1.1 h1:G2HAfAmvm/GcKan2oOQpBXOd2tT2G57ZnZGWa1PxPBQ= -github.com/cenkalti/backoff/v4 v4.1.1/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/cenkalti/backoff/v4 v4.1.2 h1:6Yo7N8UP2K6LWZnW94DLVSSrbobcWdVzAYOisuDPIFo= github.com/cenkalti/backoff/v4 v4.1.2/go.mod h1:scbssz8iZGpm3xbr14ovlUdkxfGXNInqkPWOWmG2CLw= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= -github.com/cespare/xxhash v1.1.0 h1:a6HrQnmkObjyL+Gs60czilIUGqrzKutQD6XZog3p+ko= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= @@ -141,7 +122,6 @@ github.com/cilium/ebpf v0.6.2/go.mod h1:4tRaxcgiL706VnOzHOdBlY8IEAIdxINsQBcU4xJJ github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag= github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I= -github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -155,13 +135,9 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= -github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= -github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= github.com/containerd/console v1.0.2/go.mod h1:ytZPjGgY2oeTkAONYafi2kSj0aYggsf8acV1PGKCbzQ= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/continuity v0.0.0-20190827140505-75bee3e2ccb6/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y= -github.com/containerd/continuity v0.1.0 h1:UFRRY5JemiAhPZrr/uE0n8fMTLcZsUvySPr1+D7pgr8= -github.com/containerd/continuity v0.1.0/go.mod h1:ICJu0PwR54nI0yPEnJ6jcS+J7CZAUXrLh8lPo2knzsM= github.com/containerd/continuity v0.2.2 h1:QSqfxcn8c+12slxwu00AtzXrsami0MJb/MQs9lOLHLA= github.com/containerd/continuity v0.2.2/go.mod h1:pWygW9u7LtS1o4N/Tn0FoCFDIXZ7rxcMX7HX1Dmibvk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= @@ -171,11 +147,9 @@ github.com/coreos/go-oidc/v3 v3.1.0 h1:6avEvcdvTa1qYsOZ6I5PRkSYHzpTNWgKYmaJfaYbr github.com/coreos/go-oidc/v3 v3.1.0/go.mod h1:rEJ/idjfUyfkBit1eI1fvyr+64/g9dcKpAm8MJMesvo= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= @@ -190,38 +164,27 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/denisenkom/go-mssqldb v0.0.0-20191124224453-732737034ffd/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.9.0 h1:RSohk2RsiZqLZ0zCjtfn3S4Gp4exhpBWHyQ7D0yGjAk= github.com/denisenkom/go-mssqldb v0.9.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= -github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8= -github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU= +github.com/denisenkom/go-mssqldb v0.12.0 h1:VtrkII767ttSPNRfFekePK3sctr+joXgO58stqQbtUA= +github.com/denisenkom/go-mssqldb v0.12.0/go.mod h1:iiK0YP1ZeepvmBQk/QpLEhhTNJgfzrpArPY/aFvc9yU= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.1-0.20200107013213-dc14462fd587+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no= -github.com/docker/cli v20.10.7+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/cli v20.10.8+incompatible h1:/zO/6y9IOpcehE49yMRTV9ea0nBpb8OeqSskXLNfH1E= -github.com/docker/cli v20.10.8+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v20.10.11+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/cli v20.10.12+incompatible h1:lZlz0uzG+GH+c0plStMUdF/qk3ppmgnswpR5EbqzVGA= github.com/docker/cli v20.10.12+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/docker v20.10.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker v20.10.8+incompatible h1:RVqD337BgQicVCzYrrlhLDWhq6OAD2PJDUg2LsEUvKM= -github.com/docker/docker v20.10.8+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/docker v20.10.12+incompatible h1:CEeNmFM0QZIsJCZKMkZx0ZcahTiewkrgiwfYD+dfl1U= github.com/docker/docker v20.10.12+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= github.com/docker/go-units v0.4.0 h1:3uh0PgVws3nIA0Q+MwDC8yjEPf9zjRfZZWXZYDct3Tw= github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= -github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dvyukov/go-fuzz v0.0.0-20210103155950-6a8e9d1f2415/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw= -github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= -github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= -github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= -github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/efekarakus/termcolor v1.0.1 h1:YAKFO3bnLrqZGTWyNLcYoSIAQFKVOmbqmDnwsU/znzg= github.com/efekarakus/termcolor v1.0.1/go.mod h1:AitrZNrE4nPO538fRsqf+p0WgLdAsGN5pUNrHEPsEMM= -github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -240,27 +203,24 @@ github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/fatih/set v0.2.1 h1:nn2CaJyknWE/6txyUDGwysr3G5QC6xWB/PtVjPBbeaA= github.com/fatih/set v0.2.1/go.mod h1:+RKtMCH+favT2+3YecHGxcc0b4KyVWA1QWWJUs4E0CI= -github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= -github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.7.4 h1:QmUZXrvJ9qZ3GfWvQ+2wnW/1ePrTEJqPKMYEU3lD/DM= -github.com/gin-gonic/gin v1.7.4/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.7 h1:3DoBmSbJbZAWqXJC3SLjAPfutPJJRN1U5pALB7EeTTs= github.com/gin-gonic/gin v1.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U= +github.com/glebarez/go-sqlite v1.14.7 h1:eXrKp59O5eWBfxv2Xfq5d7uex4+clKrOtWfMzzGSkoM= +github.com/glebarez/go-sqlite v1.14.7/go.mod h1:TKAw5tjyB/ocvVht7Xv4772qRAun5CG/xLCEbkDwNUc= +github.com/glebarez/sqlite v1.3.5 h1:R9op5nxb9Z10t4VXQSdAVyqRalLhWdLrlaT/iuvOGHI= +github.com/glebarez/sqlite v1.3.5/go.mod h1:ZffEtp/afVhV+jvIzQi8wlYEIkuGAYshr9OPKM/NmQc= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= -github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= @@ -274,11 +234,8 @@ github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+ github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= github.com/go-playground/validator/v10 v10.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4= -github.com/go-playground/validator/v10 v10.9.0 h1:NgTtmN58D0m8+UuxtYmGztBJB7VnPgjj221I1QHci2A= -github.com/go-playground/validator/v10 v10.9.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0= github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos= -github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= @@ -286,24 +243,20 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.0/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gofrs/uuid v4.1.0+incompatible h1:sIa2eCvUTwgjbqXrPLfNwUf9S3i3mpH1O1atV+iL/Wk= -github.com/gofrs/uuid v4.1.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.2.0+incompatible h1:yyYWMnhkhrKwwr8gAOcOCYxOOscHgDS9yZgBrnJfGa0= github.com/gofrs/uuid v4.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= -github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= -github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe h1:lXe2qZdvpiX5WZkZR4hgp4KJVfY3nMkvmwbVkpv1rVY= github.com/golang-sql/civil v0.0.0-20190719163853-cb61b32ac6fe/go.mod h1:8vg3r2VgvsThLBIFL93Qb5yWzgyZWhEmBwUJWevAkK0= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188 h1:+eHOFJl1BaXrQxKX+T06f78590z4qA2ZzBTqahsKSE4= +github.com/golang-sql/sqlexp v0.0.0-20170517235910-f1bb20e5a188/go.mod h1:vXjM/+wXQnTPR4KqTKDgJukSZ6amVRtWMPEjE6sQoK8= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/glog v1.0.0 h1:nfP3RFugxnNRyKgeWd4oI1nYvXpxrx8ck8ZrcizshdQ= github.com/golang/glog v1.0.0/go.mod h1:EWib/APOK0SL3dFbYqvxE3UYd8E6s1ouQ7iEp/0LWV4= -github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -336,7 +289,6 @@ github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaS github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -351,7 +303,6 @@ github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.6 h1:BKbKCqvP6I+rmFHt06ZmyQtvB8xAkWdhFyr0ZUNZcxQ= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.7 h1:81/ik6ipDQS2aGcBfIN5dHDB36BwrStyeAQquSYCV4o= github.com/google/go-github v17.0.0+incompatible h1:N0LgJ1j65A7kfXrZnUDaYCs/Sf4rEjNlfyDHW9dolSY= @@ -381,49 +332,37 @@ github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLe github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0= github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM= github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g= -github.com/gookit/color v1.4.2 h1:tXy44JFSFkKnELV6WaMo/lLfu/meqITX3iAV52do7lk= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0 h1:1Opow3+BWDwqor78DcJkJCIwnkviFi+rrOANki9BUFw= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU= -github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= -github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= -github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/go-grpc-middleware v1.0.0/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= -github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= github.com/grpc-ecosystem/go-grpc-middleware v1.2.2/go.mod h1:EaizFBKfUKtMIF5iaDEhniwNedqGo9FuLFzppDr3uwI= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0 h1:+9834+KizmvFV7pXQGSXQTsaWhq2GjuNUt0aUU0YBYw= github.com/grpc-ecosystem/go-grpc-middleware v1.3.0/go.mod h1:z0ButlSOZa5vEBq9m2m2hlwIgKw+rp3sdCBRoJY+30Y= github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= github.com/grpc-ecosystem/grpc-gateway v1.9.0/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= -github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/grpc-ecosystem/grpc-gateway v1.14.6/go.mod h1:zdiPV4Yse/1gnckTHtghG4GkDEdKCRJduHpTxT3/jcw= -github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw= github.com/grpc-ecosystem/grpc-gateway/v2 v2.3.0/go.mod h1:d2gYTOTUQklu06xp0AJYYmRdTVU1VKrqhkYfYag2L08= github.com/grpc-ecosystem/grpc-gateway/v2 v2.4.0/go.mod h1:IOyTYjcIO0rkmnGBfJTL0NJ11exy/Tc2QEuv7hCXp24= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0 h1:rgxjzoDmDXw5q8HONgyHhBas4to0/XWRo/gPpJhsUNQ= -github.com/grpc-ecosystem/grpc-gateway/v2 v2.6.0/go.mod h1:qrJPVzv9YlhsrxJc3P/Q85nr0w1lIRikTl4JlhdDH5w= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3 h1:I8MsauTJQXZ8df8qJvEln0kYNc3bSapuaSsEsnFdEFU= github.com/grpc-ecosystem/grpc-gateway/v2 v2.7.3/go.mod h1:lZdb/YAJUSj9OqrCHs2ihjtoO3+xK3G53wTYXFWRGDo= github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q= -github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= -github.com/hashicorp/consul/api v1.10.1/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M= github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= -github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms= github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= @@ -443,8 +382,6 @@ github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerX github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= -github.com/hashicorp/go-version v1.2.0 h1:3vNe/fWF5CBgRIguda1meWhsZHy3m8gCJ5wx+dIzX/E= -github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go-version v1.4.0 h1:aAQzgqIrRKRa7w75CKpbBxYsmUoPjzVm1W59ca1L0J4= github.com/hashicorp/go-version v1.4.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= @@ -465,8 +402,6 @@ github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKEN github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174 h1:WlZsjVhE8Af9IcZDGgJGQpNflI3+MJSBhsgT5PCtzBQ= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= -github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho= github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= @@ -474,10 +409,7 @@ github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= -github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= github.com/infobloxopen/atlas-app-toolkit v0.24.1-0.20210416193901-4c7518b07e08/go.mod h1:9BTHnpff654rY1J8KxSUOLJ+ZUDn2Vi3mmk26gQDo1M= -github.com/infobloxopen/protoc-gen-gorm v1.0.1 h1:IjvQ02gZSll+CjpWjxkLqrpxnvKAGfs5dXRJEpfZx2s= -github.com/infobloxopen/protoc-gen-gorm v1.0.1/go.mod h1:gTu86stnDQXwcNqLG9WNJfl3IPUIhxmGNqJ8z4826uo= github.com/infobloxopen/protoc-gen-gorm v1.1.0 h1:l6JKEkqMTFbtoGIfQmh/aOy7KfljgX4ql772LtG4kas= github.com/infobloxopen/protoc-gen-gorm v1.1.0/go.mod h1:ohzLmmFMWQztw2RBHunfjKSCjTPUW4JvbgU1Mdazwxg= github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= @@ -488,15 +420,9 @@ github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgO github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= -github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= -github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= -github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= github.com/jackc/pgconn v1.8.0/go.mod h1:1C2Pb36bGIP9QHGBYCjnyhqu7Rv3sGshaQUvmfGIB/o= -github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= github.com/jackc/pgconn v1.9.0/go.mod h1:YctiPyvzfU11JFxoXokUOOKQXQmDMoJL9vJzHH8/2JY= github.com/jackc/pgconn v1.9.1-0.20210724152538-d89c8390a530/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= -github.com/jackc/pgconn v1.10.0 h1:4EYhlDVEMsJ30nNj0mmgwIUXoq7e9sMJrVC2ED6QlCU= -github.com/jackc/pgconn v1.10.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.10.1/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= github.com/jackc/pgconn v1.11.0 h1:HiHArx4yFbwl91X3qqIHtUFoiIfLNJXCQRsnzkiwwaQ= github.com/jackc/pgconn v1.11.0/go.mod h1:4z2w8XhRbP1hYxkpTuBjTS3ne3J48K83+u0zoyvg2pI= @@ -514,45 +440,30 @@ github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= -github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgproto3/v2 v2.1.1 h1:7PQ/4gLoqnl87ZxL7xjO0DR5gYuviDCZxQJsUlFW1eI= github.com/jackc/pgproto3/v2 v2.1.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= github.com/jackc/pgproto3/v2 v2.2.0 h1:r7JypeP2D3onoQTCxWdTpCtJ4D+qpKr0TxvoyMhZ5ns= github.com/jackc/pgproto3/v2 v2.2.0/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= -github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= -github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= -github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= -github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= -github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= github.com/jackc/pgtype v1.8.1-0.20210724151600-32e20a603178/go.mod h1:C516IlIV9NKqfsMCXTdChteoXmwgUceqaLfjg2e3NlM= -github.com/jackc/pgtype v1.8.1 h1:9k0IXtdJXHJbyAWQgbWr1lU+MEhPXZz6RIXxfR5oxXs= -github.com/jackc/pgtype v1.8.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.9.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= +github.com/jackc/pgtype v1.9.1/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgtype v1.10.0 h1:ILnBWrRMSXGczYvmkYD6PsYyVFUNLTnIUJHHDLmqk38= github.com/jackc/pgtype v1.10.0/go.mod h1:LUMuVrfsFfdKGLw+AFFVv6KtHOFMwRgDDzBt76IqCA4= github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= -github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= -github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= -github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= -github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= github.com/jackc/pgx/v4 v4.12.1-0.20210724153913-640aa07df17c/go.mod h1:1QD0+tgSXP7iUjYm9C1NxKhny7lq6ee99u/z+IHFcgs= -github.com/jackc/pgx/v4 v4.13.0 h1:JCjhT5vmhMAf/YwBHLvrBn4OGdIQBiFG6ym8Zmdx570= -github.com/jackc/pgx/v4 v4.13.0/go.mod h1:9P4X524sErlaxj0XSGZk7s+LD0eOyu1ZDUrrpznYDF0= github.com/jackc/pgx/v4 v4.14.0/go.mod h1:jT3ibf/A0ZVCp89rtCIN0zCJxcE74ypROmHEZYsG/j8= +github.com/jackc/pgx/v4 v4.14.1/go.mod h1:RgDuE4Z34o7XE92RpLsvFiOEfrAUT0Xt2KxvX73W06M= github.com/jackc/pgx/v4 v4.15.0 h1:B7dTkXsdILD3MF987WGGCcg+tvLW6bZJdEcqVFeU//w= github.com/jackc/pgx/v4 v4.15.0/go.mod h1:D/zyOyXiaM1TmVWnOM18p0xdDtdakRBa0RsVGI3U3bw= github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= -github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= github.com/jackc/puddle v1.2.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= @@ -563,17 +474,13 @@ github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= github.com/jinzhu/now v1.0.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.3/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.4 h1:tHnRBy1i5F2Dh8BAFxqFzxKqqvezXrL2OW1TnX+Mlas= github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= -github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v1.0.0/go.mod h1:J/6gKK9jxlEcS3zixgDgUAsiuZ7yrSoa/FX5e0EB2j4= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= -github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= -github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -590,10 +497,9 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.11.7/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= -github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= -github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= @@ -621,15 +527,11 @@ github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= -github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.3.1-0.20200116171513-9eb3fc897d6f/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/lib/pq v1.10.3 h1:v9QZf2Sn6AmjXtQeFpdoq/eaNtYP6IN+7lcrygsIAtg= github.com/lib/pq v1.10.3/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= -github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w= -github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= github.com/magefile/mage v1.10.0/go.mod h1:z5UZb/iS3GoOSn0JgWuiw7dxlurVYTu+/jHXqQg881A= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.1/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= @@ -644,30 +546,24 @@ github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope github.com/mattn/go-colorable v0.1.12 h1:jF+Du6AlPIjs2BiUiQlKOX0rt3SujHxPnksPKZbaA40= github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= -github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= -github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus= -github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= -github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU= -github.com/mattn/go-sqlite3 v1.14.8/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.9/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= +github.com/mattn/go-sqlite3 v1.14.10/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsFrzQ= github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d h1:5PJl274Y63IEHC+7izoQE9x6ikvDFZS2mDVS3drnohI= github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= @@ -684,7 +580,6 @@ github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0Qu github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/mitchellh/mapstructure v1.4.2/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs= github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= github.com/moby/sys/mountinfo v0.4.1/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= @@ -699,73 +594,41 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8= github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= -github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= -github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= -github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= -github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= -github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= -github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nishanths/predeclared v0.0.0-20200524104333-86fad755b4d3/go.mod h1:nt3d53pc1VYcphSCIaYAJtnPYnr3Zyn8fMq2wvPGPso= -github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= -github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U= -github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= -github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= -github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= -github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U= github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= -github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= github.com/opencontainers/image-spec v1.0.2 h1:9yCKha/T5XdGtO0q9Q9a6T5NUCsTn/DrBg0D7ufOcFM= github.com/opencontainers/image-spec v1.0.2/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0= -github.com/opencontainers/runc v1.0.0-rc9/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U= github.com/opencontainers/runc v1.0.2/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= -github.com/opencontainers/runc v1.0.3 h1:1hbqejyQWCJBvtKAfdO0b1FmaEf2z/bxnjqbARass5k= -github.com/opencontainers/runc v1.0.3/go.mod h1:aTaHFFwQXuA71CiyxOdFFIorAoemI04suvGRQFzWTD0= github.com/opencontainers/runc v1.1.0 h1:O9+X96OcDjkmmZyfaG996kV7yq8HsoU2h1XRRQcefG8= github.com/opencontainers/runc v1.1.0/go.mod h1:Tj1hFw6eFWp/o33uxGf5yF2BX5yz2Z6iptFpuvbbKqc= github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= github.com/opencontainers/selinux v1.8.2/go.mod h1:MUIHuUEvKB1wtJjQdOyYRgOnLD2xAPP8dBsCoU0KuF8= github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= -github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= -github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= -github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= -github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= -github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= -github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= -github.com/ory/dockertest/v3 v3.7.0 h1:Bijzonc69Ont3OU0a3TWKJ1Rzlh3TsDXP1JrTAkSmsM= -github.com/ory/dockertest/v3 v3.7.0/go.mod h1:PvCCgnP7AfBZeVrzwiUTjZx/IUXlGLC1zQlUQrLIlUE= github.com/ory/dockertest/v3 v3.8.1 h1:vU/8d1We4qIad2YM0kOwRVtnyue7ExvacPiw1yDm17g= github.com/ory/dockertest/v3 v3.8.1/go.mod h1:wSRQ3wmkz+uSARYMk7kVJFDBGm8x5gSxIhI7NDc+BAQ= -github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= -github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM= github.com/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= -github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= github.com/philip-bui/grpc-zerolog v1.0.1 h1:EMacvLRUd2O1K0eWod27ZP5CY1iTNkhBDLSN+Q4JEvA= github.com/philip-bui/grpc-zerolog v1.0.1/go.mod h1:qXbiq/2X4ZUMMshsqlWyTHOcw7ns+GZmlqZZN05ZHcQ= -github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= -github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/browser v0.0.0-20180916011732-0a3d74bf9ce4/go.mod h1:4OwLy04Bl9Ef3GJJCoec+30X3LQs/0/m4HFRt/2LUSA= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= github.com/pkg/profile v1.5.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI= github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg= @@ -774,35 +637,27 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= -github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= -github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/prometheus/client_golang v1.7.1/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= -github.com/prometheus/client_golang v1.11.0 h1:HNkLOAEQMIDv/K+04rukrLx6ch7msSRwf3/SASFAGtQ= github.com/prometheus/client_golang v1.11.0/go.mod h1:Z6t4BnS23TR94PD6BsDNk8yVqroYurpAkEiz0P2BEV0= github.com/prometheus/client_golang v1.12.1 h1:ZiaPsmm9uiBeaSMRznKsCDNtPCS0T3JVDGF+06gjBzk= github.com/prometheus/client_golang v1.12.1/go.mod h1:3Z9XVyYiZYEO+YQWt3RD2R3jrbd179Rt297l4aS6nDY= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= -github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro= -github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= -github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4= github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= github.com/prometheus/common v0.26.0/go.mod h1:M7rCNAaPfAosfx8veZJCuw84e35h3Cfd9VFqTh1DIvc= github.com/prometheus/common v0.32.1 h1:hWIdL3N2HoUx3B8j3YN9mWor0qhY/NlEKZEaXxuIRh4= github.com/prometheus/common v0.32.1/go.mod h1:vu+V0TpY+O6vW9J44gczi3Ap/oXXR10b+M/gUGO4Hls= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= @@ -813,13 +668,13 @@ github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= -github.com/pterm/pterm v0.12.30 h1:ZfXzqtOJVKZ2Uhd+L5o6jmbO44PH3Mee4mxq303nh1Y= github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36 h1:Ui5zZj7xA8lXR0CxWXlKGCQMW1cZVUMOS8jEXs6ur/g= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= -github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= @@ -827,30 +682,23 @@ github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4 h1:Ha8xCaq6ln1a+R91Km45Oq6lPXj2Mla6CRJYcuV2h1w= -github.com/rogpeppe/go-internal v1.8.1-0.20211023094830-115ce09fd6b4/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= github.com/rs/xid v1.3.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= -github.com/rs/zerolog v1.26.0 h1:ORM4ibhEZeTeQlCojCK2kPz1ogAY4bGs4tD+SaAdGaE= -github.com/rs/zerolog v1.26.0/go.mod h1:yBiM87lvSqX8h0Ww4sdzNSkVYZ8dL2xjZJG1lAuGZEo= github.com/rs/zerolog v1.26.1 h1:/ihwxqH+4z8UxyI70wM1z9yCvkWcfz/a3mj48k/Zngc= github.com/rs/zerolog v1.26.1/go.mod h1:/wSSJWX7lVrsOwlbyTRSOJvqRlc+WjWlfes+CiJ+tmc= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= -github.com/sagikazarmark/crypt v0.1.0/go.mod h1:B/mN0msZuINBtQ1zZLEQcegFJJf9vnYIR88KRMEuODE= github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig= -github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/seccomp/libseccomp-golang v0.9.2-0.20210429002308-3879420cc921/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= -github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shopspring/decimal v1.2.0 h1:abSATXmQEYyShuxI4/vyW3tV1MrKAJzCZ/0zLUXYbsQ= github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= @@ -865,45 +713,30 @@ github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= -github.com/soheilhy/cmux v0.1.5 h1:jjzc5WVemNEDTLwv9tlmemhC73tI08BNOIGwBOo10Js= -github.com/soheilhy/cmux v0.1.5/go.mod h1:T7TcVDs9LWfQgPlPsdngu6I6QIoyIFZDDC6sNE1GqG0= -github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4= -github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY= github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I= github.com/spf13/afero v1.8.1 h1:izYHOT71f9iZ7iq37Uqjael60/vYC6vMtzedudZ0zEk= github.com/spf13/afero v1.8.1/go.mod h1:CtAatgMJh6bJEIs48Ay/FOnkljP3WeGUG0MC1RfAqwo= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA= github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= -github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v1.0.0/go.mod h1:/6GTrnGXV9HjY+aR4k0oJ5tcvakLuG6EuKReYlHNrgE= github.com/spf13/cobra v1.0.1-0.20201006035406-b97b5ead31f7/go.mod h1:yk5b0mALVusDL5fMM6Rd1wgnoO5jUPhwsQ6LQAJTidQ= -github.com/spf13/cobra v1.2.1 h1:+KmjbUw1hriSNMF55oPrkZcb27aECyrj8V2ytv7kWDw= -github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk= github.com/spf13/cobra v1.3.0 h1:R7cSvGu+Vv+qX0gW5R/85dx2kmmJT5z5NM8ifdYjdn0= github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4= github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk= github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo= -github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE= github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg= -github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns= -github.com/spf13/viper v1.9.0 h1:yR6EXjTp0y0cLN8OZg1CRZmOBdI88UcGkhgyJhu6nZk= -github.com/spf13/viper v1.9.0/go.mod h1:+i6ajR7OX2XaiBkrcZJFK21htRk7eDeLg7+O6bhUPP4= github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM= github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk= github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU= -github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= -github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= @@ -919,25 +752,20 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83 h1:f7nwzdAHTUUOJjHZuDvLz9CEAlUM228amCRvwzlPvsA= -github.com/tailscale/hujson v0.0.0-20211105212140-3a0adc019d83/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362 h1:xx7EMpWIKUrMMg+QanclF7bj8QTH/XYdQb/eplkmkgw= github.com/tailscale/hujson v0.0.0-20211215203138-ffd971c5f362/go.mod h1:iTDXJsA6A2wNNjurgic2rk+is6uzU4U2NLm4T+edr6M= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e h1:IWllFTiDjjLIf2oeKxpIUmtiDV5sn71VgeQgg6vcE7k= github.com/tcnksm/go-latest v0.0.0-20170313132115-e3007ae9052e/go.mod h1:d7u6HkTYKSv5m6MCKkOQlHwaShTMl3HjqSGW3XtVhXM= -github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/twitchtv/twirp v7.1.0+incompatible/go.mod h1:RRJoFSAmTEh2weEqWtpPE3vFK5YBhA6bqp2l1kfCC5A= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= -github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= -github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= @@ -962,16 +790,9 @@ github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxt github.com/zsais/go-gin-prometheus v0.1.0 h1:bkLv1XCdzqVgQ36ScgRi09MA2UC1t3tAB6nsfErsGO4= github.com/zsais/go-gin-prometheus v0.1.0/go.mod h1:Slirjzuz8uM8Cw0jmPNqbneoqcUtY2GGjn2bEd4NRLY= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= -go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= -go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs= -go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g= -go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ= go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs= -go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= -go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= @@ -1010,27 +831,24 @@ golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaE golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190530122614-20be4c3c3ed5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= -golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191205180655-e7c4368fe9dd/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20201016220609-9e8e0b390897/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= -golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210421170649-83a5a9bb288b/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e h1:MUP6MR3rJ7Gk9LEia0LP2ytiH6MuCfs7qYz+47jGdD8= -golang.org/x/crypto v0.0.0-20211202192323-5770296d904e/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20211215165025-cf75a172585e/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2 h1:XdAboW3BNMv9ocSCOk/u1MFioZGzCNkiJZ19v9Oe3Ig= golang.org/x/crypto v0.0.0-20220210151621-f4118a5b28e2/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292 h1:f+lwQ+GtmgoY+A2YaQxlSOnDjXcQ7ZRLWOHbC6HtRqE= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1071,13 +889,11 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro= golang.org/x/net v0.0.0-20180218175443-cbe0f9307d01/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= -golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= @@ -1111,7 +927,6 @@ golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81R golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= @@ -1121,10 +936,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210610132358-84b48f89b13b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c h1:7SfqwP5fxEtl/P02w5IhKc86ziJ+A25yFrkVgoy2FT8= -golang.org/x/net v0.0.0-20211205041911-012df41ee64c/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220114011407-0dd24b26b47d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd h1:O7DYs+zxREGLKzKoMQrtrEacpb0ZVXA5rIwylE2Xchk= golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= @@ -1139,7 +953,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210427180440-81ed05c6b58c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= @@ -1163,11 +976,9 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1181,18 +992,15 @@ golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191113165036-4c7a9d0fe056/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1218,6 +1026,7 @@ golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200909081042-eff7692f9009/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -1244,6 +1053,7 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20210902050250-f475640dd07b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= @@ -1252,7 +1062,6 @@ golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211205182925-97ca703d548d h1:FjkYO/PPp4Wi0EAUOVLxePm7qVW4r4ctbWpURyuOD0E= golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= @@ -1274,12 +1083,10 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -1334,6 +1141,7 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE= golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= @@ -1353,7 +1161,6 @@ golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg= @@ -1376,7 +1183,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8= google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU= google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94= -google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8= google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo= google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4= google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw= @@ -1389,7 +1195,6 @@ google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUb google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I= google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= -google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0= @@ -1402,7 +1207,6 @@ google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRn google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= -google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= @@ -1464,8 +1268,6 @@ google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEc google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247 h1:ZONpjmFT5e+I/0/xE3XXbG5OIvX2hRYzol04MhKBl2E= -google.golang.org/genproto v0.0.0-20211104193956-4c6863e31247/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= @@ -1474,15 +1276,11 @@ google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ6 google.golang.org/genproto v0.0.0-20220118154757-00ab72f36ad5/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336 h1:RK2ysGpQApbI6U7xn+ROT2rrm08lE/t8AcGqG8XI1CY= google.golang.org/genproto v0.0.0-20220210181026-6fee9acbd336/go.mod h1:kGP+zUP2Ddo0ayMi4YuN7C3WZyJvGLZRh8Z5wnAqvEI= -google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= -google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= -google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= @@ -1506,13 +1304,11 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.42.0 h1:XT2/MFpuPFsEX2fWh3YQtHkZ+WYZFQRfaUgLZYj/p6A= google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc v1.44.0 h1:weqSxi/TMs1SqFRMHCtBgXRs8k3X39QIDEZ0pRcttUg= google.golang.org/grpc v1.44.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.0.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= -google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0 h1:M1YKkFIboKNieVO5DLUEVzQfGwJD30Nv2jfUgzb5UcE= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0 h1:TLkBREm4nIsEcexnCjgQd5GQWaHcqMzwQV0TX9pq8S0= google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.2.0/go.mod h1:DNq5QpG7LJqD2AamLZ7zvKE0DEpVl2BSEVjFycAAjRY= @@ -1540,15 +1336,9 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8 gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= -gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= -gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.63.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI= gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.66.4 h1:SsAcf+mM7mRZo2nJNGt8mZCjG8ZRaNGMURJw7BsIST4= gopkg.in/ini.v1 v1.66.4/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= @@ -1556,8 +1346,6 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/square/go-jose.v2 v2.5.1/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.6.0 h1:NGk74WTnPKBNUhNzQX7PYcTLUjoq7mzKk2OKbvwk2iI= gopkg.in/square/go-jose.v2 v2.6.0/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= -gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= @@ -1571,42 +1359,29 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.0.2 h1:ChZ5VfWGB23qEr1kZosidvG9CF9HIczwoxLhBS7Ebs4= -gorm.io/datatypes v1.0.2/go.mod h1:1O1JVE4grFGcQTOGQbIBitiXUP6Sv84/KZU7eWeUv1k= gorm.io/datatypes v1.0.5 h1:3vHCfg4Bz8SDx83zE+ASskF+g/j0kWrcKrY9jFUyAl0= gorm.io/datatypes v1.0.5/go.mod h1:acG/OHGwod+1KrbwPL1t+aavb7jOBOETeyl5M8K5VQs= -gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M= -gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM= gorm.io/driver/mysql v1.2.2/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= gorm.io/driver/mysql v1.2.3 h1:cZqzlOfg5Kf1VIdLC1D9hT6Cy9BgxhExLj/2tIgUe7Y= gorm.io/driver/mysql v1.2.3/go.mod h1:qsiz+XcAyMrS6QY+X3M9R6b/lKM1imKmcuK9kac5LTo= -gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= -gorm.io/driver/postgres v1.1.1 h1:tWLmqYCyaoh89fi7DhM6QggujrOnmfo3H98AzgNAAu0= -gorm.io/driver/postgres v1.1.1/go.mod h1:tpe2xN7aCst1NUdYyWQyxPtnHC+Zfp6NEux9PXD1OU0= +gorm.io/driver/mysql v1.3.2 h1:QJryWiqQ91EvZ0jZL48NOpdlPdMjdip1hQ8bTgo4H7I= +gorm.io/driver/mysql v1.3.2/go.mod h1:ChK6AHbHgDCFZyJp0F+BmVGb06PSIoh9uVYKAlRbb2U= gorm.io/driver/postgres v1.2.3 h1:f4t0TmNMy9gh3TU2PX+EppoA6YsgFnyq8Ojtddb42To= gorm.io/driver/postgres v1.2.3/go.mod h1:pJV6RgYQPG47aM1f0QeOzFH9HxQc8JcmAgjRCgS0wjs= -gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= -gorm.io/driver/sqlite v1.1.5 h1:JU8G59VyKu1x1RMQgjefQnkZjDe9wHc1kARDZPu5dZs= -gorm.io/driver/sqlite v1.1.5/go.mod h1:NpaYMcVKEh6vLJ47VP6T7Weieu4H1Drs3dGD/K6GrGc= -gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= -gorm.io/driver/sqlite v1.2.6/go.mod h1:gyoX0vHiiwi0g49tv+x2E7l8ksauLK0U/gShcdUsjWY= -gorm.io/driver/sqlserver v1.0.9 h1:P7Dm/BKqsrOjyhRSnLXvG2g1W/eJUgxdrdBwgJw3tEg= -gorm.io/driver/sqlserver v1.0.9/go.mod h1:iBdxY2CepkTt9Q1r84RbZA1qCai300Qlp8kQf9qE9II= -gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= -gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.14/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= -gorm.io/gorm v1.21.15 h1:gAyaDoPw0lCyrSFWhBlahbUA1U4P5RViC1uIqoB+1Rk= -gorm.io/gorm v1.21.15/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/driver/postgres v1.3.1 h1:Pyv+gg1Gq1IgsLYytj/S2k7ebII3CzEdpqQkPOdH24g= +gorm.io/driver/postgres v1.3.1/go.mod h1:WwvWOuR9unCLpGWCL6Y3JOeBWvbKi6JLhayiVclSZZU= +gorm.io/driver/sqlite v1.3.1 h1:bwfE+zTEWklBYoEodIOIBwuWHpnx52Z9zJFW5F33WLk= +gorm.io/driver/sqlite v1.3.1/go.mod h1:wJx0hJspfycZ6myN38x1O/AqLtNS6c5o9TndewFbELg= +gorm.io/driver/sqlserver v1.3.1 h1:F5t6ScMzOgy1zukRTIZgLZwKahgt3q1woAILVolKpOI= +gorm.io/driver/sqlserver v1.3.1/go.mod h1:w25Vrx2BG+CJNUu/xKbFhaKlGxT/nzRkhWCCoptX8tQ= gorm.io/gorm v1.22.3/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= gorm.io/gorm v1.22.4/go.mod h1:1aeVC+pe9ZmvKZban/gW4QPra7PRoTEssyc922qCAkk= -gorm.io/gorm v1.22.5 h1:lYREBgc02Be/5lSCTuysZZDb6ffL2qrat6fg9CFbvXU= gorm.io/gorm v1.22.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= -gotest.tools/v3 v3.0.2 h1:kG1BFyqVHuQoVQiR1bWGnfz/fmHvvuiSPIV7rvl360E= +gorm.io/gorm v1.23.1 h1:aj5IlhDzEPsoIyOPtTRVI+SyaN1u6k613sbt4pwbxG0= +gorm.io/gorm v1.23.1/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.0.3 h1:4AuOwCGf4lLR9u3YOe2awrHygurzhO/HeQ6laiA6Sx0= gotest.tools/v3 v3.0.3/go.mod h1:Z7Lb0S5l+klDB31fvDQX8ss/FlKDxtlFlw3Oa8Ymbl8= -honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -1616,14 +1391,131 @@ honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9 honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6 h1:acCzuUSQ79tGsM/O50VRFySfMm19IoMKL+sZztZkCxw= inet.af/netaddr v0.0.0-20211027220019-c74959edd3b6/go.mod h1:y3MGhcFMlh0KZPMuXXow8mpjxxAk3yoDNsp4cQz54i8= +lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk= +modernc.org/cc/v3 v3.33.6/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.9/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.33.11/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.34.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.0/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.4/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.5/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.7/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.8/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.10/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.15/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.16/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.17/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.18/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.20/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/cc/v3 v3.35.22/go.mod h1:iPJg1pkwXqAV16SNgFBVYmggfMg6xhs+2oiO0vclK3g= +modernc.org/ccgo/v3 v3.9.5/go.mod h1:umuo2EP2oDSBnD3ckjaVUXMrmeAw8C8OSICVa0iFf60= +modernc.org/ccgo/v3 v3.10.0/go.mod h1:c0yBmkRFi7uW4J7fwx/JiijwOjeAeR2NoSaRVFPmjMw= +modernc.org/ccgo/v3 v3.11.0/go.mod h1:dGNposbDp9TOZ/1KBxghxtUp/bzErD0/0QW4hhSaBMI= +modernc.org/ccgo/v3 v3.11.1/go.mod h1:lWHxfsn13L3f7hgGsGlU28D9eUOf6y3ZYHKoPaKU0ag= +modernc.org/ccgo/v3 v3.11.3/go.mod h1:0oHunRBMBiXOKdaglfMlRPBALQqsfrCKXgw9okQ3GEw= +modernc.org/ccgo/v3 v3.12.4/go.mod h1:Bk+m6m2tsooJchP/Yk5ji56cClmN6R1cqc9o/YtbgBQ= +modernc.org/ccgo/v3 v3.12.6/go.mod h1:0Ji3ruvpFPpz+yu+1m0wk68pdr/LENABhTrDkMDWH6c= +modernc.org/ccgo/v3 v3.12.8/go.mod h1:Hq9keM4ZfjCDuDXxaHptpv9N24JhgBZmUG5q60iLgUo= +modernc.org/ccgo/v3 v3.12.11/go.mod h1:0jVcmyDwDKDGWbcrzQ+xwJjbhZruHtouiBEvDfoIsdg= +modernc.org/ccgo/v3 v3.12.14/go.mod h1:GhTu1k0YCpJSuWwtRAEHAol5W7g1/RRfS4/9hc9vF5I= +modernc.org/ccgo/v3 v3.12.18/go.mod h1:jvg/xVdWWmZACSgOiAhpWpwHWylbJaSzayCqNOJKIhs= +modernc.org/ccgo/v3 v3.12.20/go.mod h1:aKEdssiu7gVgSy/jjMastnv/q6wWGRbszbheXgWRHc8= +modernc.org/ccgo/v3 v3.12.21/go.mod h1:ydgg2tEprnyMn159ZO/N4pLBqpL7NOkJ88GT5zNU2dE= +modernc.org/ccgo/v3 v3.12.22/go.mod h1:nyDVFMmMWhMsgQw+5JH6B6o4MnZ+UQNw1pp52XYFPRk= +modernc.org/ccgo/v3 v3.12.25/go.mod h1:UaLyWI26TwyIT4+ZFNjkyTbsPsY3plAEB6E7L/vZV3w= +modernc.org/ccgo/v3 v3.12.29/go.mod h1:FXVjG7YLf9FetsS2OOYcwNhcdOLGt8S9bQ48+OP75cE= +modernc.org/ccgo/v3 v3.12.36/go.mod h1:uP3/Fiezp/Ga8onfvMLpREq+KUjUmYMxXPO8tETHtA8= +modernc.org/ccgo/v3 v3.12.38/go.mod h1:93O0G7baRST1vNj4wnZ49b1kLxt0xCW5Hsa2qRaZPqc= +modernc.org/ccgo/v3 v3.12.43/go.mod h1:k+DqGXd3o7W+inNujK15S5ZYuPoWYLpF5PYougCmthU= +modernc.org/ccgo/v3 v3.12.46/go.mod h1:UZe6EvMSqOxaJ4sznY7b23/k13R8XNlyWsO5bAmSgOE= +modernc.org/ccgo/v3 v3.12.47/go.mod h1:m8d6p0zNps187fhBwzY/ii6gxfjob1VxWb919Nk1HUk= +modernc.org/ccgo/v3 v3.12.50/go.mod h1:bu9YIwtg+HXQxBhsRDE+cJjQRuINuT9PUK4orOco/JI= +modernc.org/ccgo/v3 v3.12.51/go.mod h1:gaIIlx4YpmGO2bLye04/yeblmvWEmE4BBBls4aJXFiE= +modernc.org/ccgo/v3 v3.12.53/go.mod h1:8xWGGTFkdFEWBEsUmi+DBjwu/WLy3SSOrqEmKUjMeEg= +modernc.org/ccgo/v3 v3.12.54/go.mod h1:yANKFTm9llTFVX1FqNKHE0aMcQb1fuPJx6p8AcUx+74= +modernc.org/ccgo/v3 v3.12.55/go.mod h1:rsXiIyJi9psOwiBkplOaHye5L4MOOaCjHg1Fxkj7IeU= +modernc.org/ccgo/v3 v3.12.56/go.mod h1:ljeFks3faDseCkr60JMpeDb2GSO3TKAmrzm7q9YOcMU= +modernc.org/ccgo/v3 v3.12.57/go.mod h1:hNSF4DNVgBl8wYHpMvPqQWDQx8luqxDnNGCMM4NFNMc= +modernc.org/ccgo/v3 v3.12.60/go.mod h1:k/Nn0zdO1xHVWjPYVshDeWKqbRWIfif5dtsIOCUVMqM= +modernc.org/ccgo/v3 v3.12.66/go.mod h1:jUuxlCFZTUZLMV08s7B1ekHX5+LIAurKTTaugUr/EhQ= +modernc.org/ccgo/v3 v3.12.67/go.mod h1:Bll3KwKvGROizP2Xj17GEGOTrlvB1XcVaBrC90ORO84= +modernc.org/ccgo/v3 v3.12.73/go.mod h1:hngkB+nUUqzOf3iqsM48Gf1FZhY599qzVg1iX+BT3cQ= +modernc.org/ccgo/v3 v3.12.81/go.mod h1:p2A1duHoBBg1mFtYvnhAnQyI6vL0uw5PGYLSIgF6rYY= +modernc.org/ccgo/v3 v3.12.84/go.mod h1:ApbflUfa5BKadjHynCficldU1ghjen84tuM5jRynB7w= +modernc.org/ccgo/v3 v3.12.86/go.mod h1:dN7S26DLTgVSni1PVA3KxxHTcykyDurf3OgUzNqTSrU= +modernc.org/ccgo/v3 v3.12.90/go.mod h1:obhSc3CdivCRpYZmrvO88TXlW0NvoSVvdh/ccRjJYko= +modernc.org/ccgo/v3 v3.12.92/go.mod h1:5yDdN7ti9KWPi5bRVWPl8UNhpEAtCjuEE7ayQnzzqHA= +modernc.org/ccgo/v3 v3.13.1/go.mod h1:aBYVOUfIlcSnrsRVU8VRS35y2DIfpgkmVkYZ0tpIXi4= +modernc.org/ccgo/v3 v3.14.0/go.mod h1:hBrkiBlUwvr5vV/ZH9YzXIp982jKE8Ek8tR1ytoAL6Q= +modernc.org/ccgo/v3 v3.15.1/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.9/go.mod h1:md59wBwDT2LznX/OTCPoVS6KIsdRgY8xqQwBV+hkTH0= +modernc.org/ccgo/v3 v3.15.10/go.mod h1:wQKxoFn0ynxMuCLfFD09c8XPUCc8obfchoVR9Cn0fI8= +modernc.org/ccorpus v1.11.1/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ= +modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM= +modernc.org/libc v1.9.8/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/libc v1.9.11/go.mod h1:NyF3tsA5ArIjJ83XB0JlqhjTabTCHm9aX4XMPHyQn0Q= +modernc.org/libc v1.11.0/go.mod h1:2lOfPmj7cz+g1MrPNmX65QCzVxgNq2C5o0jdLY2gAYg= +modernc.org/libc v1.11.2/go.mod h1:ioIyrl3ETkugDO3SGZ+6EOKvlP3zSOycUETe4XM4n8M= +modernc.org/libc v1.11.5/go.mod h1:k3HDCP95A6U111Q5TmG3nAyUcp3kR5YFZTeDS9v8vSU= +modernc.org/libc v1.11.6/go.mod h1:ddqmzR6p5i4jIGK1d/EiSw97LBcE3dK24QEwCFvgNgE= +modernc.org/libc v1.11.11/go.mod h1:lXEp9QOOk4qAYOtL3BmMve99S5Owz7Qyowzvg6LiZso= +modernc.org/libc v1.11.13/go.mod h1:ZYawJWlXIzXy2Pzghaf7YfM8OKacP3eZQI81PDLFdY8= +modernc.org/libc v1.11.16/go.mod h1:+DJquzYi+DMRUtWI1YNxrlQO6TcA5+dRRiq8HWBWRC8= +modernc.org/libc v1.11.19/go.mod h1:e0dgEame6mkydy19KKaVPBeEnyJB4LGNb0bBH1EtQ3I= +modernc.org/libc v1.11.24/go.mod h1:FOSzE0UwookyT1TtCJrRkvsOrX2k38HoInhw+cSCUGk= +modernc.org/libc v1.11.26/go.mod h1:SFjnYi9OSd2W7f4ct622o/PAYqk7KHv6GS8NZULIjKY= +modernc.org/libc v1.11.27/go.mod h1:zmWm6kcFXt/jpzeCgfvUNswM0qke8qVwxqZrnddlDiE= +modernc.org/libc v1.11.28/go.mod h1:Ii4V0fTFcbq3qrv3CNn+OGHAvzqMBvC7dBNyC4vHZlg= +modernc.org/libc v1.11.31/go.mod h1:FpBncUkEAtopRNJj8aRo29qUiyx5AvAlAxzlx9GNaVM= +modernc.org/libc v1.11.34/go.mod h1:+Tzc4hnb1iaX/SKAutJmfzES6awxfU1BPvrrJO0pYLg= +modernc.org/libc v1.11.37/go.mod h1:dCQebOwoO1046yTrfUE5nX1f3YpGZQKNcITUYWlrAWo= +modernc.org/libc v1.11.39/go.mod h1:mV8lJMo2S5A31uD0k1cMu7vrJbSA3J3waQJxpV4iqx8= +modernc.org/libc v1.11.42/go.mod h1:yzrLDU+sSjLE+D4bIhS7q1L5UwXDOw99PLSX0BlZvSQ= +modernc.org/libc v1.11.44/go.mod h1:KFq33jsma7F5WXiYelU8quMJasCCTnHK0mkri4yPHgA= +modernc.org/libc v1.11.45/go.mod h1:Y192orvfVQQYFzCNsn+Xt0Hxt4DiO4USpLNXBlXg/tM= +modernc.org/libc v1.11.47/go.mod h1:tPkE4PzCTW27E6AIKIR5IwHAQKCAtudEIeAV1/SiyBg= +modernc.org/libc v1.11.49/go.mod h1:9JrJuK5WTtoTWIFQ7QjX2Mb/bagYdZdscI3xrvHbXjE= +modernc.org/libc v1.11.51/go.mod h1:R9I8u9TS+meaWLdbfQhq2kFknTW0O3aw3kEMqDDxMaM= +modernc.org/libc v1.11.53/go.mod h1:5ip5vWYPAoMulkQ5XlSJTy12Sz5U6blOQiYasilVPsU= +modernc.org/libc v1.11.54/go.mod h1:S/FVnskbzVUrjfBqlGFIPA5m7UwB3n9fojHhCNfSsnw= +modernc.org/libc v1.11.55/go.mod h1:j2A5YBRm6HjNkoSs/fzZrSxCuwWqcMYTDPLNx0URn3M= +modernc.org/libc v1.11.56/go.mod h1:pakHkg5JdMLt2OgRadpPOTnyRXm/uzu+Yyg/LSLdi18= +modernc.org/libc v1.11.58/go.mod h1:ns94Rxv0OWyoQrDqMFfWwka2BcaF6/61CqJRK9LP7S8= +modernc.org/libc v1.11.71/go.mod h1:DUOmMYe+IvKi9n6Mycyx3DbjfzSKrdr/0Vgt3j7P5gw= +modernc.org/libc v1.11.75/go.mod h1:dGRVugT6edz361wmD9gk6ax1AbDSe0x5vji0dGJiPT0= +modernc.org/libc v1.11.82/go.mod h1:NF+Ek1BOl2jeC7lw3a7Jj5PWyHPwWD4aq3wVKxqV1fI= +modernc.org/libc v1.11.86/go.mod h1:ePuYgoQLmvxdNT06RpGnaDKJmDNEkV7ZPKI2jnsvZoE= +modernc.org/libc v1.11.87/go.mod h1:Qvd5iXTeLhI5PS0XSyqMY99282y+3euapQFxM7jYnpY= +modernc.org/libc v1.11.88/go.mod h1:h3oIVe8dxmTcchcFuCcJ4nAWaoiwzKCdv82MM0oiIdQ= +modernc.org/libc v1.11.98/go.mod h1:ynK5sbjsU77AP+nn61+k+wxUGRx9rOFcIqWYYMaDZ4c= +modernc.org/libc v1.11.101/go.mod h1:wLLYgEiY2D17NbBOEp+mIJJJBGSiy7fLL4ZrGGZ+8jI= +modernc.org/libc v1.12.0/go.mod h1:2MH3DaF/gCU8i/UBiVE1VFRos4o523M7zipmwH8SIgQ= +modernc.org/libc v1.13.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.13.2/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.1/go.mod h1:npFeGWjmZTjFeWALQLrvklVmAxv4m80jnG3+xI8FdJk= +modernc.org/libc v1.14.2/go.mod h1:MX1GBLnRLNdvmK9azU9LCxZ5lMyhrbEMK8rG3X/Fe34= +modernc.org/libc v1.14.3 h1:ruQJ8VDhnWkUR/otUG/Ksw+sWHUw9cPAq6mjDaY/Y7c= +modernc.org/libc v1.14.3/go.mod h1:GPIvQVOVPizzlqyRX3l756/3ppsAgg1QgPxjr5Q4agQ= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.4.1 h1:ij3fYGe8zBF4Vu+g0oT7mB06r8sqGWKuJu1yXeR4by8= +modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +modernc.org/memory v1.0.5 h1:XRch8trV7GgvTec2i7jc33YlUI0RKVDBvZ5eZ5m8y14= +modernc.org/memory v1.0.5/go.mod h1:B7OYswTRnfGg+4tDH1t1OeUNnsy2viGTdME4tzd+IjM= +modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0= +modernc.org/sqlite v1.14.5 h1:bYrrjwH9Y7QUGk1MbchZDhRfmpGuEAs/D45sVjNbfvs= +modernc.org/sqlite v1.14.5/go.mod h1:YyX5Rx0WbXokitdWl2GJIDy4BrPxBP0PwwhpXOHCDLE= +modernc.org/strutil v1.1.1/go.mod h1:DE+MQQ/hjKBZS2zNInV5hhcipt5rLPWkmpbGeW5mmdw= +modernc.org/tcl v1.10.0/go.mod h1:WzWapmP/7dHVhFoyPpEaNSVTL8xtewhouN/cqSJ5A2s= +modernc.org/token v1.0.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= +modernc.org/z v1.2.21/go.mod h1:uXrObx4pGqXWIMliC5MiKuwAyMrltzwpteOFUP1PWCc= +modernc.org/z v1.3.0/go.mod h1:+mvgLH814oDjtATDdT3rs84JnUIpkvAF5B8AVkNlE2g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0= rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA= -sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= -tailscale.com v1.20.3 h1:C3g2AgmQaOi0YT5dAal9mslugPXMxwj0EXY7YfL2QrA= -tailscale.com v1.20.3/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= tailscale.com v1.20.4 h1:7cl/Q2Sbo2Jb2dX7zA+Exbbl7DT5UGZ4iGhQ2xj23X0= tailscale.com v1.20.4/go.mod h1:kjVy3ji2OH5lZhPLIIRacoY3CN4Bo3Yyb2mtoM8nfJ4= From 67f5c32b49c68a873d095760315dd1e5ac9a8544 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Tue, 22 Feb 2022 19:04:52 +0000 Subject: [PATCH 35/38] Only allow one connection to sqlite --- db.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/db.go b/db.go index 7aadd20a..90026cea 100644 --- a/db.go +++ b/db.go @@ -85,6 +85,9 @@ func (h *Headscale) openDB() (*gorm.DB, error) { DisableForeignKeyConstraintWhenMigrating: true, Logger: log, }) + + sqlDB, _ := db.DB() + sqlDB.SetMaxOpenConns(1) case Postgres: db, err = gorm.Open(postgres.Open(h.dbString), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true, From 48c866b058374fbf79473509fae108f11428eff3 Mon Sep 17 00:00:00 2001 From: pernila Date: Tue, 22 Feb 2022 23:06:35 +0200 Subject: [PATCH 36/38] Added FreeBSD to the supported clients Added FreeBSD to the supported clients Now in ports: https://www.freshports.org/security/headscale/ --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index e7ba6649..76d7566e 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,7 @@ If you would like to sponsor features, bugs or prioritisation, reach out to one | ------- | ----------------------------------------------------------------------------------------------------------------- | | Linux | Yes | | OpenBSD | Yes | +| FreeBSD | Yes | | macOS | Yes (see `/apple` on your headscale for more information) | | Windows | Yes [docs](./docs/windows-client.md) | | Android | [You need to compile the client yourself](https://github.com/juanfont/headscale/issues/58#issuecomment-885255270) | From d4761da27cd5fcf609b89f076a32c84cae2b3070 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 22 Feb 2022 22:34:27 +0000 Subject: [PATCH 37/38] docs(README): update contributors --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index 071dd2bd..b21d6042 100644 --- a/README.md +++ b/README.md @@ -430,6 +430,13 @@ make build + + + pernila/ +
+ pernila +
+ Wakeful-Cloud/ From 686e45cf27b9d509530f590fefffb90941cbdcbc Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Wed, 23 Feb 2022 16:15:20 +0000 Subject: [PATCH 38/38] Set all anti-cgo options and add comment --- db.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/db.go b/db.go index 90026cea..feee7474 100644 --- a/db.go +++ b/db.go @@ -2,6 +2,7 @@ package headscale import ( "errors" + "time" "github.com/glebarez/sqlite" "gorm.io/driver/postgres" @@ -81,13 +82,24 @@ func (h *Headscale) openDB() (*gorm.DB, error) { switch h.dbType { case Sqlite: - db, err = gorm.Open(sqlite.Open(h.dbString), &gorm.Config{ - DisableForeignKeyConstraintWhenMigrating: true, - Logger: log, - }) + db, err = gorm.Open( + sqlite.Open(h.dbString+"?_synchronous=1&_journal_mode=WAL"), + &gorm.Config{ + DisableForeignKeyConstraintWhenMigrating: true, + Logger: log, + }, + ) + db.Exec("PRAGMA foreign_keys=ON") + + // The pure Go SQLite library does not handle locking in + // the same way as the C based one and we cant use the gorm + // connection pool as of 2022/02/23. sqlDB, _ := db.DB() + sqlDB.SetMaxIdleConns(1) sqlDB.SetMaxOpenConns(1) + sqlDB.SetConnMaxIdleTime(time.Hour) + case Postgres: db, err = gorm.Open(postgres.Open(h.dbString), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true,