mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	feat(namespace): add normalization function for namespace
This commit is contained in:
		
							parent
							
								
									69cdfbb56f
								
							
						
					
					
						commit
						92ffac625e
					
				
							
								
								
									
										6
									
								
								dns.go
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								dns.go
									
									
									
									
									
								
							@ -165,11 +165,7 @@ func getMapResponseDNSConfig(
 | 
				
			|||||||
			dnsConfig.Domains,
 | 
								dnsConfig.Domains,
 | 
				
			||||||
			fmt.Sprintf(
 | 
								fmt.Sprintf(
 | 
				
			||||||
				"%s.%s",
 | 
									"%s.%s",
 | 
				
			||||||
				strings.ReplaceAll(
 | 
									machine.Namespace.Name,
 | 
				
			||||||
					machine.Namespace.Name,
 | 
					 | 
				
			||||||
					"@",
 | 
					 | 
				
			||||||
					".",
 | 
					 | 
				
			||||||
				), // Replace @ with . for valid domain for machine
 | 
					 | 
				
			||||||
				baseDomain,
 | 
									baseDomain,
 | 
				
			||||||
			),
 | 
								),
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
 | 
				
			|||||||
@ -724,11 +724,7 @@ func (machine Machine) toNode(
 | 
				
			|||||||
		hostname = fmt.Sprintf(
 | 
							hostname = fmt.Sprintf(
 | 
				
			||||||
			"%s.%s.%s",
 | 
								"%s.%s.%s",
 | 
				
			||||||
			machine.Name,
 | 
								machine.Name,
 | 
				
			||||||
			strings.ReplaceAll(
 | 
								machine.Namespace.Name,
 | 
				
			||||||
				machine.Namespace.Name,
 | 
					 | 
				
			||||||
				"@",
 | 
					 | 
				
			||||||
				".",
 | 
					 | 
				
			||||||
			), // Replace @ with . for valid domain for machine
 | 
					 | 
				
			||||||
			baseDomain,
 | 
								baseDomain,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
				
			|||||||
@ -2,7 +2,10 @@ package headscale
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"errors"
 | 
						"errors"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"regexp"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
 | 
						v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
 | 
				
			||||||
@ -16,8 +19,11 @@ const (
 | 
				
			|||||||
	errNamespaceExists          = Error("Namespace already exists")
 | 
						errNamespaceExists          = Error("Namespace already exists")
 | 
				
			||||||
	errNamespaceNotFound        = Error("Namespace not found")
 | 
						errNamespaceNotFound        = Error("Namespace not found")
 | 
				
			||||||
	errNamespaceNotEmptyOfNodes = Error("Namespace not empty: node(s) found")
 | 
						errNamespaceNotEmptyOfNodes = Error("Namespace not empty: node(s) found")
 | 
				
			||||||
 | 
						errInvalidNamespaceName     = Error("Invalid namespace name")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					var normalizeNamespaceRegex = regexp.MustCompile("[^a-z0-9-.]+")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Namespace is the way Headscale implements the concept of users in Tailscale
 | 
					// Namespace is the way Headscale implements the concept of users in Tailscale
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
// At the end of the day, users in Tailscale are some kind of 'bubbles' or namespaces
 | 
					// At the end of the day, users in Tailscale are some kind of 'bubbles' or namespaces
 | 
				
			||||||
@ -30,7 +36,12 @@ type Namespace struct {
 | 
				
			|||||||
// CreateNamespace creates a new Namespace. Returns error if could not be created
 | 
					// CreateNamespace creates a new Namespace. Returns error if could not be created
 | 
				
			||||||
// or another namespace already exists.
 | 
					// or another namespace already exists.
 | 
				
			||||||
func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
 | 
					func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
	namespace := Namespace{}
 | 
						namespace := Namespace{}
 | 
				
			||||||
 | 
						name, err = NormalizeNamespaceName(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if err := h.db.Where("name = ?", name).First(&namespace).Error; err == nil {
 | 
						if err := h.db.Where("name = ?", name).First(&namespace).Error; err == nil {
 | 
				
			||||||
		return nil, errNamespaceExists
 | 
							return nil, errNamespaceExists
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -50,6 +61,10 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
 | 
				
			|||||||
// DestroyNamespace destroys a Namespace. Returns error if the Namespace does
 | 
					// DestroyNamespace destroys a Namespace. Returns error if the Namespace does
 | 
				
			||||||
// not exist or if there are machines associated with it.
 | 
					// not exist or if there are machines associated with it.
 | 
				
			||||||
func (h *Headscale) DestroyNamespace(name string) error {
 | 
					func (h *Headscale) DestroyNamespace(name string) error {
 | 
				
			||||||
 | 
						name, err := NormalizeNamespaceName(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	namespace, err := h.GetNamespace(name)
 | 
						namespace, err := h.GetNamespace(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errNamespaceNotFound
 | 
							return errNamespaceNotFound
 | 
				
			||||||
@ -84,10 +99,15 @@ func (h *Headscale) DestroyNamespace(name string) error {
 | 
				
			|||||||
// RenameNamespace renames a Namespace. Returns error if the Namespace does
 | 
					// RenameNamespace renames a Namespace. Returns error if the Namespace does
 | 
				
			||||||
// not exist or if another Namespace exists with the new name.
 | 
					// not exist or if another Namespace exists with the new name.
 | 
				
			||||||
func (h *Headscale) RenameNamespace(oldName, newName string) error {
 | 
					func (h *Headscale) RenameNamespace(oldName, newName string) error {
 | 
				
			||||||
 | 
						var err error
 | 
				
			||||||
	oldNamespace, err := h.GetNamespace(oldName)
 | 
						oldNamespace, err := h.GetNamespace(oldName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						newName, err = NormalizeNamespaceName(newName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	_, err = h.GetNamespace(newName)
 | 
						_, err = h.GetNamespace(newName)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		return errNamespaceExists
 | 
							return errNamespaceExists
 | 
				
			||||||
@ -108,6 +128,10 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error {
 | 
				
			|||||||
// GetNamespace fetches a namespace by name.
 | 
					// GetNamespace fetches a namespace by name.
 | 
				
			||||||
func (h *Headscale) GetNamespace(name string) (*Namespace, error) {
 | 
					func (h *Headscale) GetNamespace(name string) (*Namespace, error) {
 | 
				
			||||||
	namespace := Namespace{}
 | 
						namespace := Namespace{}
 | 
				
			||||||
 | 
						name, err := NormalizeNamespaceName(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	if result := h.db.First(&namespace, "name = ?", name); errors.Is(
 | 
						if result := h.db.First(&namespace, "name = ?", name); errors.Is(
 | 
				
			||||||
		result.Error,
 | 
							result.Error,
 | 
				
			||||||
		gorm.ErrRecordNotFound,
 | 
							gorm.ErrRecordNotFound,
 | 
				
			||||||
@ -130,6 +154,10 @@ func (h *Headscale) ListNamespaces() ([]Namespace, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ListMachinesInNamespace gets all the nodes in a given namespace.
 | 
					// ListMachinesInNamespace gets all the nodes in a given namespace.
 | 
				
			||||||
func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) {
 | 
					func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) {
 | 
				
			||||||
 | 
						name, err := NormalizeNamespaceName(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	namespace, err := h.GetNamespace(name)
 | 
						namespace, err := h.GetNamespace(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -145,6 +173,10 @@ func (h *Headscale) ListMachinesInNamespace(name string) ([]Machine, error) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// ListSharedMachinesInNamespace returns all the machines that are shared to the specified namespace.
 | 
					// ListSharedMachinesInNamespace returns all the machines that are shared to the specified namespace.
 | 
				
			||||||
func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error) {
 | 
					func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error) {
 | 
				
			||||||
 | 
						name, err := NormalizeNamespaceName(name)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	namespace, err := h.GetNamespace(name)
 | 
						namespace, err := h.GetNamespace(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
@ -170,6 +202,10 @@ func (h *Headscale) ListSharedMachinesInNamespace(name string) ([]Machine, error
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
// SetMachineNamespace assigns a Machine to a namespace.
 | 
					// SetMachineNamespace assigns a Machine to a namespace.
 | 
				
			||||||
func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error {
 | 
					func (h *Headscale) SetMachineNamespace(machine *Machine, namespaceName string) error {
 | 
				
			||||||
 | 
						namespaceName, err := NormalizeNamespaceName(namespaceName)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	namespace, err := h.GetNamespace(namespaceName)
 | 
						namespace, err := h.GetNamespace(namespaceName)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
@ -233,3 +269,24 @@ func (n *Namespace) toProto() *v1.Namespace {
 | 
				
			|||||||
		CreatedAt: timestamppb.New(n.CreatedAt),
 | 
							CreatedAt: timestamppb.New(n.CreatedAt),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// NormalizeNamespaceName will replace forbidden chars in namespace
 | 
				
			||||||
 | 
					// it can also return an error if the namespace doesn't respect RFC 952 and 1123
 | 
				
			||||||
 | 
					func NormalizeNamespaceName(name string) (string, error) {
 | 
				
			||||||
 | 
						name = strings.ToLower(name)
 | 
				
			||||||
 | 
						name = strings.ReplaceAll(name, "@", ".")
 | 
				
			||||||
 | 
						name = strings.ReplaceAll(name, "'", "")
 | 
				
			||||||
 | 
						name = normalizeNamespaceRegex.ReplaceAllString(name, "-")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, elt := range strings.Split(name, ".") {
 | 
				
			||||||
 | 
							if len(elt) > 63 {
 | 
				
			||||||
 | 
								return "", fmt.Errorf(
 | 
				
			||||||
 | 
									"label %v is more than 63 chars: %w",
 | 
				
			||||||
 | 
									elt,
 | 
				
			||||||
 | 
									errInvalidNamespaceName,
 | 
				
			||||||
 | 
								)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return name, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -1,6 +1,8 @@
 | 
				
			|||||||
package headscale
 | 
					package headscale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"testing"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"gopkg.in/check.v1"
 | 
						"gopkg.in/check.v1"
 | 
				
			||||||
	"gorm.io/gorm"
 | 
						"gorm.io/gorm"
 | 
				
			||||||
@ -239,3 +241,62 @@ func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	c.Assert(found, check.Equals, true)
 | 
						c.Assert(found, check.Equals, true)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TestNormalizeNamespaceName(t *testing.T) {
 | 
				
			||||||
 | 
						type args struct {
 | 
				
			||||||
 | 
							name string
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						tests := []struct {
 | 
				
			||||||
 | 
							name    string
 | 
				
			||||||
 | 
							args    args
 | 
				
			||||||
 | 
							want    string
 | 
				
			||||||
 | 
							wantErr bool
 | 
				
			||||||
 | 
						}{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "normalize simple name",
 | 
				
			||||||
 | 
								args:    args{name: "normalize-simple.name"},
 | 
				
			||||||
 | 
								want:    "normalize-simple.name",
 | 
				
			||||||
 | 
								wantErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "normalize an email",
 | 
				
			||||||
 | 
								args:    args{name: "foo.bar@example.com"},
 | 
				
			||||||
 | 
								want:    "foo.bar.example.com",
 | 
				
			||||||
 | 
								wantErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "normalize complex email",
 | 
				
			||||||
 | 
								args:    args{name: "foo.bar+complex-email@example.com"},
 | 
				
			||||||
 | 
								want:    "foo.bar-complex-email.example.com",
 | 
				
			||||||
 | 
								wantErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "namespace name with space",
 | 
				
			||||||
 | 
								args:    args{name: "name space"},
 | 
				
			||||||
 | 
								want:    "name-space",
 | 
				
			||||||
 | 
								wantErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								name:    "namespace with quote",
 | 
				
			||||||
 | 
								args:    args{name: "Jamie's iPhone 5"},
 | 
				
			||||||
 | 
								want:    "jamies-iphone-5",
 | 
				
			||||||
 | 
								wantErr: false,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, tt := range tests {
 | 
				
			||||||
 | 
							t.Run(tt.name, func(t *testing.T) {
 | 
				
			||||||
 | 
								got, err := NormalizeNamespaceName(tt.args.name)
 | 
				
			||||||
 | 
								if (err != nil) != tt.wantErr {
 | 
				
			||||||
 | 
									t.Errorf(
 | 
				
			||||||
 | 
										"NormalizeNamespaceName() error = %v, wantErr %v",
 | 
				
			||||||
 | 
										err,
 | 
				
			||||||
 | 
										tt.wantErr,
 | 
				
			||||||
 | 
									)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if got != tt.want {
 | 
				
			||||||
 | 
									t.Errorf("NormalizeNamespaceName() = %v, want %v", got, tt.want)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										180
									
								
								oidc_test.go
									
									
									
									
									
								
							
							
						
						
									
										180
									
								
								oidc_test.go
									
									
									
									
									
								
							@ -1,180 +0,0 @@
 | 
				
			|||||||
package headscale
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	"sync"
 | 
					 | 
				
			||||||
	"testing"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	"github.com/coreos/go-oidc/v3/oidc"
 | 
					 | 
				
			||||||
	"github.com/patrickmn/go-cache"
 | 
					 | 
				
			||||||
	"golang.org/x/oauth2"
 | 
					 | 
				
			||||||
	"gorm.io/gorm"
 | 
					 | 
				
			||||||
	"tailscale.com/tailcfg"
 | 
					 | 
				
			||||||
	"tailscale.com/types/key"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func TestHeadscale_getNamespaceFromEmail(t *testing.T) {
 | 
					 | 
				
			||||||
	type fields struct {
 | 
					 | 
				
			||||||
		cfg             Config
 | 
					 | 
				
			||||||
		db              *gorm.DB
 | 
					 | 
				
			||||||
		dbString        string
 | 
					 | 
				
			||||||
		dbType          string
 | 
					 | 
				
			||||||
		dbDebug         bool
 | 
					 | 
				
			||||||
		privateKey      *key.MachinePrivate
 | 
					 | 
				
			||||||
		aclPolicy       *ACLPolicy
 | 
					 | 
				
			||||||
		aclRules        []tailcfg.FilterRule
 | 
					 | 
				
			||||||
		lastStateChange sync.Map
 | 
					 | 
				
			||||||
		oidcProvider    *oidc.Provider
 | 
					 | 
				
			||||||
		oauth2Config    *oauth2.Config
 | 
					 | 
				
			||||||
		oidcStateCache  *cache.Cache
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	type args struct {
 | 
					 | 
				
			||||||
		email string
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	tests := []struct {
 | 
					 | 
				
			||||||
		name   string
 | 
					 | 
				
			||||||
		fields fields
 | 
					 | 
				
			||||||
		args   args
 | 
					 | 
				
			||||||
		want   string
 | 
					 | 
				
			||||||
		want1  bool
 | 
					 | 
				
			||||||
	}{
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "match all",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							".*": "space",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "test@example.no",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "space",
 | 
					 | 
				
			||||||
			want1: true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "match user",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							"specific@user\\.no": "user-namespace",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "specific@user.no",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "user-namespace",
 | 
					 | 
				
			||||||
			want1: true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "match domain",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							".*@example\\.no": "example",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "test@example.no",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "example",
 | 
					 | 
				
			||||||
			want1: true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "multi match domain",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							".*@example\\.no": "exammple",
 | 
					 | 
				
			||||||
							".*@gmail\\.com":  "gmail",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "someuser@gmail.com",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "gmail",
 | 
					 | 
				
			||||||
			want1: true,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "no match domain",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							".*@dontknow.no": "never",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "test@wedontknow.no",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "",
 | 
					 | 
				
			||||||
			want1: false,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		{
 | 
					 | 
				
			||||||
			name: "multi no match domain",
 | 
					 | 
				
			||||||
			fields: fields{
 | 
					 | 
				
			||||||
				cfg: Config{
 | 
					 | 
				
			||||||
					OIDC: OIDCConfig{
 | 
					 | 
				
			||||||
						MatchMap: map[string]string{
 | 
					 | 
				
			||||||
							".*@dontknow.no":   "never",
 | 
					 | 
				
			||||||
							".*@wedontknow.no": "other",
 | 
					 | 
				
			||||||
							".*\\.no":          "stuffy",
 | 
					 | 
				
			||||||
						},
 | 
					 | 
				
			||||||
					},
 | 
					 | 
				
			||||||
				},
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			args: args{
 | 
					 | 
				
			||||||
				email: "tasy@nonofthem.com",
 | 
					 | 
				
			||||||
			},
 | 
					 | 
				
			||||||
			want:  "",
 | 
					 | 
				
			||||||
			want1: false,
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	//nolint
 | 
					 | 
				
			||||||
	for _, test := range tests {
 | 
					 | 
				
			||||||
		t.Run(test.name, func(t *testing.T) {
 | 
					 | 
				
			||||||
			app := &Headscale{
 | 
					 | 
				
			||||||
				cfg:             test.fields.cfg,
 | 
					 | 
				
			||||||
				db:              test.fields.db,
 | 
					 | 
				
			||||||
				dbString:        test.fields.dbString,
 | 
					 | 
				
			||||||
				dbType:          test.fields.dbType,
 | 
					 | 
				
			||||||
				dbDebug:         test.fields.dbDebug,
 | 
					 | 
				
			||||||
				privateKey:      test.fields.privateKey,
 | 
					 | 
				
			||||||
				aclPolicy:       test.fields.aclPolicy,
 | 
					 | 
				
			||||||
				aclRules:        test.fields.aclRules,
 | 
					 | 
				
			||||||
				lastStateChange: test.fields.lastStateChange,
 | 
					 | 
				
			||||||
				oidcProvider:    test.fields.oidcProvider,
 | 
					 | 
				
			||||||
				oauth2Config:    test.fields.oauth2Config,
 | 
					 | 
				
			||||||
				oidcStateCache:  test.fields.oidcStateCache,
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			got, got1 := app.getNamespaceFromEmail(test.args.email)
 | 
					 | 
				
			||||||
			if got != test.want {
 | 
					 | 
				
			||||||
				t.Errorf(
 | 
					 | 
				
			||||||
					"Headscale.getNamespaceFromEmail() got = %v, want %v",
 | 
					 | 
				
			||||||
					got,
 | 
					 | 
				
			||||||
					test.want,
 | 
					 | 
				
			||||||
				)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			if got1 != test.want1 {
 | 
					 | 
				
			||||||
				t.Errorf(
 | 
					 | 
				
			||||||
					"Headscale.getNamespaceFromEmail() got1 = %v, want %v",
 | 
					 | 
				
			||||||
					got1,
 | 
					 | 
				
			||||||
					test.want1,
 | 
					 | 
				
			||||||
				)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user