mirror of
https://github.com/juanfont/headscale.git
synced 2025-07-27 13:48:02 +02:00
fixups
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
d28194ac86
commit
7633c2e4cc
@ -449,7 +449,6 @@ func TestBackfillIPAddresses(t *testing.T) {
|
|||||||
"UserID",
|
"UserID",
|
||||||
"Endpoints",
|
"Endpoints",
|
||||||
"Hostinfo",
|
"Hostinfo",
|
||||||
"Routes",
|
|
||||||
"CreatedAt",
|
"CreatedAt",
|
||||||
"UpdatedAt",
|
"UpdatedAt",
|
||||||
))
|
))
|
||||||
|
@ -101,15 +101,22 @@ func generateUserProfiles(
|
|||||||
node *types.Node,
|
node *types.Node,
|
||||||
peers types.Nodes,
|
peers types.Nodes,
|
||||||
) []tailcfg.UserProfile {
|
) []tailcfg.UserProfile {
|
||||||
userMap := make(map[uint]types.User)
|
userMap := make(map[uint]*types.User)
|
||||||
userMap[node.User.ID] = node.User
|
ids := make([]uint, 0, len(userMap))
|
||||||
|
userMap[node.User.ID] = &node.User
|
||||||
|
ids = append(ids, node.User.ID)
|
||||||
for _, peer := range peers {
|
for _, peer := range peers {
|
||||||
userMap[peer.User.ID] = peer.User // not worth checking if already is there
|
userMap[peer.User.ID] = &peer.User
|
||||||
|
ids = append(ids, peer.User.ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
slices.Sort(ids)
|
||||||
|
slices.Compact(ids)
|
||||||
var profiles []tailcfg.UserProfile
|
var profiles []tailcfg.UserProfile
|
||||||
for _, user := range userMap {
|
for _, id := range ids {
|
||||||
profiles = append(profiles, user.TailscaleUserProfile())
|
if userMap[id] != nil {
|
||||||
|
profiles = append(profiles, userMap[id].TailscaleUserProfile())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return profiles
|
return profiles
|
||||||
|
@ -11,7 +11,6 @@ import (
|
|||||||
"github.com/juanfont/headscale/hscontrol/policy"
|
"github.com/juanfont/headscale/hscontrol/policy"
|
||||||
"github.com/juanfont/headscale/hscontrol/routes"
|
"github.com/juanfont/headscale/hscontrol/routes"
|
||||||
"github.com/juanfont/headscale/hscontrol/types"
|
"github.com/juanfont/headscale/hscontrol/types"
|
||||||
"gopkg.in/check.v1"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
"tailscale.com/net/tsaddr"
|
"tailscale.com/net/tsaddr"
|
||||||
"tailscale.com/tailcfg"
|
"tailscale.com/tailcfg"
|
||||||
@ -24,51 +23,6 @@ var iap = func(ipStr string) *netip.Addr {
|
|||||||
return &ip
|
return &ip
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
|
|
||||||
mach := func(hostname, username string, userid uint) *types.Node {
|
|
||||||
return &types.Node{
|
|
||||||
Hostname: hostname,
|
|
||||||
UserID: userid,
|
|
||||||
User: types.User{
|
|
||||||
Model: gorm.Model{
|
|
||||||
ID: userid,
|
|
||||||
},
|
|
||||||
Name: username,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeInShared1 := mach("test_get_shared_nodes_1", "user1", 1)
|
|
||||||
nodeInShared2 := mach("test_get_shared_nodes_2", "user2", 2)
|
|
||||||
nodeInShared3 := mach("test_get_shared_nodes_3", "user3", 3)
|
|
||||||
node2InShared1 := mach("test_get_shared_nodes_4", "user1", 1)
|
|
||||||
|
|
||||||
userProfiles := generateUserProfiles(
|
|
||||||
nodeInShared1,
|
|
||||||
types.Nodes{
|
|
||||||
nodeInShared2, nodeInShared3, node2InShared1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
c.Assert(len(userProfiles), check.Equals, 3)
|
|
||||||
|
|
||||||
users := []string{
|
|
||||||
"user1", "user2", "user3",
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, user := range users {
|
|
||||||
found := false
|
|
||||||
for _, userProfile := range userProfiles {
|
|
||||||
if userProfile.DisplayName == user {
|
|
||||||
found = true
|
|
||||||
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.Assert(found, check.Equals, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestDNSConfigMapResponse(t *testing.T) {
|
func TestDNSConfigMapResponse(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
magicDNS bool
|
magicDNS bool
|
||||||
|
@ -2165,6 +2165,9 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
netip.MustParsePrefix("10.33.0.0/16"),
|
netip.MustParsePrefix("10.33.0.0/16"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: []netip.Prefix{
|
||||||
|
netip.MustParsePrefix("10.33.0.0/16"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
&types.Node{
|
&types.Node{
|
||||||
@ -2292,6 +2295,7 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: tsaddr.ExitRoutes(),
|
RoutableIPs: tsaddr.ExitRoutes(),
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: tsaddr.ExitRoutes(),
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
&types.Node{
|
&types.Node{
|
||||||
@ -2398,6 +2402,7 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: tsaddr.ExitRoutes(),
|
RoutableIPs: tsaddr.ExitRoutes(),
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: tsaddr.ExitRoutes(),
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
&types.Node{
|
&types.Node{
|
||||||
@ -2513,6 +2518,10 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
netip.MustParsePrefix("16.0.0.0/16"),
|
netip.MustParsePrefix("16.0.0.0/16"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: []netip.Prefix{
|
||||||
|
netip.MustParsePrefix("8.0.0.0/16"),
|
||||||
|
netip.MustParsePrefix("16.0.0.0/16"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
&types.Node{
|
&types.Node{
|
||||||
@ -2603,6 +2612,10 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
netip.MustParsePrefix("16.0.0.0/8"),
|
netip.MustParsePrefix("16.0.0.0/8"),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: []netip.Prefix{
|
||||||
|
netip.MustParsePrefix("8.0.0.0/8"),
|
||||||
|
netip.MustParsePrefix("16.0.0.0/8"),
|
||||||
|
},
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
&types.Node{
|
&types.Node{
|
||||||
@ -2683,6 +2696,7 @@ func TestReduceFilterRules(t *testing.T) {
|
|||||||
Hostinfo: &tailcfg.Hostinfo{
|
Hostinfo: &tailcfg.Hostinfo{
|
||||||
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")},
|
RoutableIPs: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")},
|
||||||
},
|
},
|
||||||
|
ApprovedRoutes: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/24")},
|
||||||
ForcedTags: []string{"tag:access-servers"},
|
ForcedTags: []string{"tag:access-servers"},
|
||||||
},
|
},
|
||||||
peers: types.Nodes{
|
peers: types.Nodes{
|
||||||
|
@ -9,8 +9,8 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Match struct {
|
type Match struct {
|
||||||
Srcs *netipx.IPSet
|
srcs *netipx.IPSet
|
||||||
Dests *netipx.IPSet
|
dests *netipx.IPSet
|
||||||
}
|
}
|
||||||
|
|
||||||
func MatchFromFilterRule(rule tailcfg.FilterRule) Match {
|
func MatchFromFilterRule(rule tailcfg.FilterRule) Match {
|
||||||
@ -42,16 +42,16 @@ func MatchFromStrings(sources, destinations []string) Match {
|
|||||||
destsSet, _ := dests.IPSet()
|
destsSet, _ := dests.IPSet()
|
||||||
|
|
||||||
match := Match{
|
match := Match{
|
||||||
Srcs: srcsSet,
|
srcs: srcsSet,
|
||||||
Dests: destsSet,
|
dests: destsSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
return match
|
return match
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Match) SrcsContainsIPs(ips []netip.Addr) bool {
|
func (m *Match) SrcsContainsIPs(ips ...netip.Addr) bool {
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
if m.Srcs.Contains(ip) {
|
if m.srcs.Contains(ip) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -59,9 +59,29 @@ func (m *Match) SrcsContainsIPs(ips []netip.Addr) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *Match) DestsContainsIP(ips []netip.Addr) bool {
|
func (m *Match) DestsContainsIP(ips ...netip.Addr) bool {
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
if m.Dests.Contains(ip) {
|
if m.dests.Contains(ip) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) SrcsOverlapsPrefixes(prefixes ...netip.Prefix) bool {
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if m.srcs.ContainsPrefix(prefix) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *Match) DestsOverlapsPrefixes(prefixes ...netip.Prefix) bool {
|
||||||
|
for _, prefix := range prefixes {
|
||||||
|
if m.dests.ContainsPrefix(prefix) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -202,11 +202,15 @@ func (node *Node) CanAccess(filter []tailcfg.FilterRule, node2 *Node) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, matcher := range matchers {
|
for _, matcher := range matchers {
|
||||||
if !matcher.SrcsContainsIPs(src) {
|
if !matcher.SrcsContainsIPs(src...) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if matcher.DestsContainsIP(allowedIPs) {
|
if matcher.DestsContainsIP(allowedIPs...) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if matcher.DestsOverlapsPrefixes(node2.SubnetRoutes()...) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,13 @@ type User struct {
|
|||||||
ProfilePicURL string
|
ProfilePicURL string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (u *User) StringID() string {
|
||||||
|
if u == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return strconv.FormatUint(uint64(u.ID), 10)
|
||||||
|
}
|
||||||
|
|
||||||
// Username is the main way to get the username of a user,
|
// Username is the main way to get the username of a user,
|
||||||
// it will return the email if it exists, the name if it exists,
|
// it will return the email if it exists, the name if it exists,
|
||||||
// the OIDCIdentifier if it exists, and the ID if nothing else exists.
|
// the OIDCIdentifier if it exists, and the ID if nothing else exists.
|
||||||
@ -63,7 +70,11 @@ type User struct {
|
|||||||
// should be used throughout headscale, in information returned to the
|
// should be used throughout headscale, in information returned to the
|
||||||
// user and the Policy engine.
|
// user and the Policy engine.
|
||||||
func (u *User) Username() string {
|
func (u *User) Username() string {
|
||||||
return cmp.Or(u.Email, u.Name, u.ProviderIdentifier.String, strconv.FormatUint(uint64(u.ID), 10))
|
return cmp.Or(
|
||||||
|
u.Email,
|
||||||
|
u.Name,
|
||||||
|
u.ProviderIdentifier.String,
|
||||||
|
u.StringID())
|
||||||
}
|
}
|
||||||
|
|
||||||
// DisplayNameOrUsername returns the DisplayName if it exists, otherwise
|
// DisplayNameOrUsername returns the DisplayName if it exists, otherwise
|
||||||
|
Loading…
Reference in New Issue
Block a user