mirror of
				https://github.com/juanfont/headscale.git
				synced 2025-10-28 10:51:44 +01:00 
			
		
		
		
	Merge branch 'main' into typofix
This commit is contained in:
		
						commit
						e93529e9f3
					
				
							
								
								
									
										2
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								.github/workflows/lint.yml
									
									
									
									
										vendored
									
									
								
							@ -70,7 +70,7 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v2
 | 
					      - uses: actions/checkout@v2
 | 
				
			||||||
      - uses: bufbuild/buf-setup-action@v0.7.0
 | 
					      - uses: bufbuild/buf-setup-action@v1.7.0
 | 
				
			||||||
      - uses: bufbuild/buf-lint-action@v1
 | 
					      - uses: bufbuild/buf-lint-action@v1
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          input: "proto"
 | 
					          input: "proto"
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										27
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										27
									
								
								.github/workflows/test-integration.yml
									
									
									
									
										vendored
									
									
								
							@ -11,6 +11,11 @@ jobs:
 | 
				
			|||||||
        with:
 | 
					        with:
 | 
				
			||||||
          fetch-depth: 2
 | 
					          fetch-depth: 2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Set Swap Space
 | 
				
			||||||
 | 
					        uses: pierotofy/set-swap-space@master
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          swap-size-gb: 10
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Get changed files
 | 
					      - name: Get changed files
 | 
				
			||||||
        id: changed-files
 | 
					        id: changed-files
 | 
				
			||||||
        uses: tj-actions/changed-files@v14.1
 | 
					        uses: tj-actions/changed-files@v14.1
 | 
				
			||||||
@ -25,11 +30,29 @@ jobs:
 | 
				
			|||||||
      - uses: cachix/install-nix-action@v16
 | 
					      - uses: cachix/install-nix-action@v16
 | 
				
			||||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
					        if: steps.changed-files.outputs.any_changed == 'true'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Run Integration tests
 | 
					      - name: Run CLI integration tests
 | 
				
			||||||
        if: steps.changed-files.outputs.any_changed == 'true'
 | 
					        if: steps.changed-files.outputs.any_changed == 'true'
 | 
				
			||||||
        uses: nick-fields/retry@v2
 | 
					        uses: nick-fields/retry@v2
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          timeout_minutes: 240
 | 
					          timeout_minutes: 240
 | 
				
			||||||
          max_attempts: 5
 | 
					          max_attempts: 5
 | 
				
			||||||
          retry_on: error
 | 
					          retry_on: error
 | 
				
			||||||
          command: nix develop --command -- make test_integration
 | 
					          command: nix develop --command -- make test_integration_cli
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Run Embedded DERP server integration tests
 | 
				
			||||||
 | 
					        if: steps.changed-files.outputs.any_changed == 'true'
 | 
				
			||||||
 | 
					        uses: nick-fields/retry@v2
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          timeout_minutes: 240
 | 
				
			||||||
 | 
					          max_attempts: 5
 | 
				
			||||||
 | 
					          retry_on: error
 | 
				
			||||||
 | 
					          command: nix develop --command -- make test_integration_derp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      - name: Run general integration tests
 | 
				
			||||||
 | 
					        if: steps.changed-files.outputs.any_changed == 'true'
 | 
				
			||||||
 | 
					        uses: nick-fields/retry@v2
 | 
				
			||||||
 | 
					        with:
 | 
				
			||||||
 | 
					          timeout_minutes: 240
 | 
				
			||||||
 | 
					          max_attempts: 5
 | 
				
			||||||
 | 
					          retry_on: error
 | 
				
			||||||
 | 
					          command: nix develop --command -- make test_integration_general
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										10
									
								
								Makefile
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								Makefile
									
									
									
									
									
								
							@ -24,14 +24,16 @@ dev: lint test build
 | 
				
			|||||||
test:
 | 
					test:
 | 
				
			||||||
	@go test -coverprofile=coverage.out ./...
 | 
						@go test -coverprofile=coverage.out ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_integration:
 | 
					test_integration: test_integration_cli test_integration_derp test_integration_general
 | 
				
			||||||
	go test -failfast -tags integration -timeout 30m -count=1 ./...
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_integration_cli:
 | 
					test_integration_cli:
 | 
				
			||||||
	go test -tags integration -v integration_cli_test.go integration_common_test.go
 | 
						go test -failfast -tags integration_cli,integration -timeout 30m -count=1 ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
test_integration_derp:
 | 
					test_integration_derp:
 | 
				
			||||||
	go test -tags integration -v integration_embedded_derp_test.go integration_common_test.go
 | 
						go test -failfast -tags integration_derp,integration -timeout 30m -count=1 ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					test_integration_general:
 | 
				
			||||||
 | 
						go test -failfast -tags integration_general,integration -timeout 30m -count=1 ./...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
coverprofile_func:
 | 
					coverprofile_func:
 | 
				
			||||||
	go tool cover -func=coverage.out
 | 
						go tool cover -func=coverage.out
 | 
				
			||||||
 | 
				
			|||||||
@ -14,7 +14,7 @@ const (
 | 
				
			|||||||
	apiPrefixLength = 7
 | 
						apiPrefixLength = 7
 | 
				
			||||||
	apiKeyLength    = 32
 | 
						apiKeyLength    = 32
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errAPIKeyFailedToParse = Error("Failed to parse ApiKey")
 | 
						ErrAPIKeyFailedToParse = Error("Failed to parse ApiKey")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// APIKey describes the datamodel for API keys used to remotely authenticate with
 | 
					// APIKey describes the datamodel for API keys used to remotely authenticate with
 | 
				
			||||||
@ -116,7 +116,7 @@ func (h *Headscale) ExpireAPIKey(key *APIKey) error {
 | 
				
			|||||||
func (h *Headscale) ValidateAPIKey(keyStr string) (bool, error) {
 | 
					func (h *Headscale) ValidateAPIKey(keyStr string) (bool, error) {
 | 
				
			||||||
	prefix, hash, found := strings.Cut(keyStr, ".")
 | 
						prefix, hash, found := strings.Cut(keyStr, ".")
 | 
				
			||||||
	if !found {
 | 
						if !found {
 | 
				
			||||||
		return false, errAPIKeyFailedToParse
 | 
							return false, ErrAPIKeyFailedToParse
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key, err := h.GetAPIKey(prefix)
 | 
						key, err := h.GetAPIKey(prefix)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										6
									
								
								db.go
									
									
									
									
									
								
							
							
						
						
									
										6
									
								
								db.go
									
									
									
									
									
								
							@ -248,7 +248,7 @@ func (hi *HostInfo) Scan(destination interface{}) error {
 | 
				
			|||||||
		return json.Unmarshal([]byte(value), hi)
 | 
							return json.Unmarshal([]byte(value), hi)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination)
 | 
							return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -270,7 +270,7 @@ func (i *IPPrefixes) Scan(destination interface{}) error {
 | 
				
			|||||||
		return json.Unmarshal([]byte(value), i)
 | 
							return json.Unmarshal([]byte(value), i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination)
 | 
							return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -292,7 +292,7 @@ func (i *StringList) Scan(destination interface{}) error {
 | 
				
			|||||||
		return json.Unmarshal([]byte(value), i)
 | 
							return json.Unmarshal([]byte(value), i)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination)
 | 
							return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
//go:build integration
 | 
					//go:build integration_cli
 | 
				
			||||||
// +build integration
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package headscale
 | 
					package headscale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -73,21 +72,22 @@ func (s *IntegrationCLITestSuite) SetupTest() {
 | 
				
			|||||||
		s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Println("Creating headscale container")
 | 
						fmt.Println("Creating headscale container for CLI tests")
 | 
				
			||||||
	if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
						if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
				
			||||||
		s.headscale = *pheadscale
 | 
							s.headscale = *pheadscale
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		s.FailNow(fmt.Sprintf("Could not start headscale container: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not start headscale container: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fmt.Println("Created headscale container")
 | 
						fmt.Println("Created headscale container for CLI tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fmt.Println("Waiting for headscale to be ready")
 | 
						fmt.Println("Waiting for headscale to be ready for CLI tests")
 | 
				
			||||||
	hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8080/tcp"))
 | 
						hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8080/tcp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := s.pool.Retry(func() error {
 | 
						if err := s.pool.Retry(func() error {
 | 
				
			||||||
		url := fmt.Sprintf("http://%s/health", hostEndpoint)
 | 
							url := fmt.Sprintf("http://%s/health", hostEndpoint)
 | 
				
			||||||
		resp, err := http.Get(url)
 | 
							resp, err := http.Get(url)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Printf("headscale for CLI test is not ready: %s\n", err)
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		if resp.StatusCode != http.StatusOK {
 | 
							if resp.StatusCode != http.StatusOK {
 | 
				
			||||||
@ -102,7 +102,7 @@ func (s *IntegrationCLITestSuite) SetupTest() {
 | 
				
			|||||||
		// https://github.com/stretchr/testify/issues/849
 | 
							// https://github.com/stretchr/testify/issues/849
 | 
				
			||||||
		return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
							return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	fmt.Println("headscale container is ready")
 | 
						fmt.Println("headscale container is ready for CLI tests")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *IntegrationCLITestSuite) TearDownTest() {
 | 
					func (s *IntegrationCLITestSuite) TearDownTest() {
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
//go:build integration
 | 
					//go:build integration
 | 
				
			||||||
// +build integration
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package headscale
 | 
					package headscale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -20,6 +19,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
 | 
						headscaleHostname      = "headscale-derp"
 | 
				
			||||||
	DOCKER_EXECUTE_TIMEOUT = 10 * time.Second
 | 
						DOCKER_EXECUTE_TIMEOUT = 10 * time.Second
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -30,9 +30,10 @@ var (
 | 
				
			|||||||
	IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48")
 | 
						IpPrefix6 = netaddr.MustParseIPPrefix("fd7a:115c:a1e0::/48")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	tailscaleVersions = []string{
 | 
						tailscaleVersions = []string{
 | 
				
			||||||
		"head",
 | 
							// "head",
 | 
				
			||||||
		"unstable",
 | 
							// "unstable",
 | 
				
			||||||
		"1.26.0",
 | 
							"1.28.0",
 | 
				
			||||||
 | 
							"1.26.2",
 | 
				
			||||||
		"1.24.2",
 | 
							"1.24.2",
 | 
				
			||||||
		"1.22.2",
 | 
							"1.22.2",
 | 
				
			||||||
		"1.20.4",
 | 
							"1.20.4",
 | 
				
			||||||
 | 
				
			|||||||
@ -1,4 +1,4 @@
 | 
				
			|||||||
//go:build integration
 | 
					//go:build integration_derp
 | 
				
			||||||
 | 
					
 | 
				
			||||||
package headscale
 | 
					package headscale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -28,9 +28,8 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	headscaleHostname = "headscale-derp"
 | 
						namespaceName   = "derpnamespace"
 | 
				
			||||||
	namespaceName     = "derpnamespace"
 | 
						totalContainers = 3
 | 
				
			||||||
	totalContainers   = 3
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type IntegrationDERPTestSuite struct {
 | 
					type IntegrationDERPTestSuite struct {
 | 
				
			||||||
@ -134,15 +133,15 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
 | 
				
			|||||||
		s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Creating headscale container")
 | 
						log.Println("Creating headscale container for DERP integration tests")
 | 
				
			||||||
	if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
						if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
				
			||||||
		s.headscale = *pheadscale
 | 
							s.headscale = *pheadscale
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		s.FailNow(fmt.Sprintf("Could not start headscale container: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not start headscale container: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.Println("Created headscale container to test DERP")
 | 
						log.Println("Created headscale container for embedded DERP tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Creating tailscale containers")
 | 
						log.Println("Creating tailscale containers for embedded DERP tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < totalContainers; i++ {
 | 
						for i := 0; i < totalContainers; i++ {
 | 
				
			||||||
		version := tailscaleVersions[i%len(tailscaleVersions)]
 | 
							version := tailscaleVersions[i%len(tailscaleVersions)]
 | 
				
			||||||
@ -154,7 +153,7 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
 | 
				
			|||||||
		s.tailscales[hostname] = *container
 | 
							s.tailscales[hostname] = *container
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Waiting for headscale to be ready")
 | 
						log.Println("Waiting for headscale to be ready for embedded DERP tests")
 | 
				
			||||||
	hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8443/tcp"))
 | 
						hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8443/tcp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := s.pool.Retry(func() error {
 | 
						if err := s.pool.Retry(func() error {
 | 
				
			||||||
@ -164,6 +163,7 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
 | 
				
			|||||||
		client := &http.Client{Transport: insecureTransport}
 | 
							client := &http.Client{Transport: insecureTransport}
 | 
				
			||||||
		resp, err := client.Get(url)
 | 
							resp, err := client.Get(url)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Printf("headscale for embedded DERP tests is not ready: %s\n", err)
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -179,7 +179,7 @@ func (s *IntegrationDERPTestSuite) SetupSuite() {
 | 
				
			|||||||
		// https://github.com/stretchr/testify/issues/849
 | 
							// https://github.com/stretchr/testify/issues/849
 | 
				
			||||||
		return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
							return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.Println("headscale container is ready")
 | 
						log.Println("headscale container is ready for embedded DERP tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Printf("Creating headscale namespace: %s\n", namespaceName)
 | 
						log.Printf("Creating headscale namespace: %s\n", namespaceName)
 | 
				
			||||||
	result, err := ExecuteCommand(
 | 
						result, err := ExecuteCommand(
 | 
				
			||||||
 | 
				
			|||||||
@ -1,5 +1,4 @@
 | 
				
			|||||||
//go:build integration
 | 
					//go:build integration_general
 | 
				
			||||||
// +build integration
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
package headscale
 | 
					package headscale
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -251,15 +250,15 @@ func (s *IntegrationTestSuite) SetupSuite() {
 | 
				
			|||||||
		s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not remove existing container before building test: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Creating headscale container")
 | 
						log.Println("Creating headscale container for core integration tests")
 | 
				
			||||||
	if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
						if pheadscale, err := s.pool.BuildAndRunWithBuildOptions(headscaleBuildOptions, headscaleOptions, DockerRestartPolicy); err == nil {
 | 
				
			||||||
		s.headscale = *pheadscale
 | 
							s.headscale = *pheadscale
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		s.FailNow(fmt.Sprintf("Could not start headscale container: %s", err), "")
 | 
							s.FailNow(fmt.Sprintf("Could not start headscale container for core integration tests: %s", err), "")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.Println("Created headscale container")
 | 
						log.Println("Created headscale container for core integration tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Creating tailscale containers")
 | 
						log.Println("Creating tailscale containers for core integration tests")
 | 
				
			||||||
	for namespace, scales := range s.namespaces {
 | 
						for namespace, scales := range s.namespaces {
 | 
				
			||||||
		for i := 0; i < scales.count; i++ {
 | 
							for i := 0; i < scales.count; i++ {
 | 
				
			||||||
			version := tailscaleVersions[i%len(tailscaleVersions)]
 | 
								version := tailscaleVersions[i%len(tailscaleVersions)]
 | 
				
			||||||
@ -273,7 +272,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	log.Println("Waiting for headscale to be ready")
 | 
						log.Println("Waiting for headscale to be ready for core integration tests")
 | 
				
			||||||
	hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8080/tcp"))
 | 
						hostEndpoint := fmt.Sprintf("localhost:%s", s.headscale.GetPort("8080/tcp"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := s.pool.Retry(func() error {
 | 
						if err := s.pool.Retry(func() error {
 | 
				
			||||||
@ -281,6 +280,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		resp, err := http.Get(url)
 | 
							resp, err := http.Get(url)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								fmt.Printf("headscale for core integration test is not ready: %s\n", err)
 | 
				
			||||||
			return err
 | 
								return err
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -296,7 +296,7 @@ func (s *IntegrationTestSuite) SetupSuite() {
 | 
				
			|||||||
		// https://github.com/stretchr/testify/issues/849
 | 
							// https://github.com/stretchr/testify/issues/849
 | 
				
			||||||
		return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
							return // fmt.Errorf("Could not connect to headscale: %s", err)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	log.Println("headscale container is ready")
 | 
						log.Println("headscale container is ready for core integration tests")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for namespace, scales := range s.namespaces {
 | 
						for namespace, scales := range s.namespaces {
 | 
				
			||||||
		log.Printf("Creating headscale namespace: %s\n", namespace)
 | 
							log.Printf("Creating headscale namespace: %s\n", namespace)
 | 
				
			||||||
							
								
								
									
										24
									
								
								machine.go
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								machine.go
									
									
									
									
									
								
							@ -18,14 +18,14 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	errMachineNotFound                  = Error("machine not found")
 | 
						ErrMachineNotFound                  = Error("machine not found")
 | 
				
			||||||
	errMachineRouteIsNotAvailable       = Error("route is not available on machine")
 | 
						ErrMachineRouteIsNotAvailable       = Error("route is not available on machine")
 | 
				
			||||||
	errMachineAddressesInvalid          = Error("failed to parse machine addresses")
 | 
						ErrMachineAddressesInvalid          = Error("failed to parse machine addresses")
 | 
				
			||||||
	errMachineNotFoundRegistrationCache = Error(
 | 
						ErrMachineNotFoundRegistrationCache = Error(
 | 
				
			||||||
		"machine not found in registration cache",
 | 
							"machine not found in registration cache",
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	errCouldNotConvertMachineInterface = Error("failed to convert machine interface")
 | 
						ErrCouldNotConvertMachineInterface = Error("failed to convert machine interface")
 | 
				
			||||||
	errHostnameTooLong                 = Error("Hostname too long")
 | 
						ErrHostnameTooLong                 = Error("Hostname too long")
 | 
				
			||||||
	MachineGivenNameHashLength         = 8
 | 
						MachineGivenNameHashLength         = 8
 | 
				
			||||||
	MachineGivenNameTrimSize           = 2
 | 
						MachineGivenNameTrimSize           = 2
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -112,7 +112,7 @@ func (ma *MachineAddresses) Scan(destination interface{}) error {
 | 
				
			|||||||
		return nil
 | 
							return nil
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		return fmt.Errorf("%w: unexpected data type %T", errMachineAddressesInvalid, destination)
 | 
							return fmt.Errorf("%w: unexpected data type %T", ErrMachineAddressesInvalid, destination)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -337,7 +337,7 @@ func (h *Headscale) GetMachine(namespace string, name string) (*Machine, error)
 | 
				
			|||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, errMachineNotFound
 | 
						return nil, ErrMachineNotFound
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// GetMachineByID finds a Machine by ID and returns the Machine struct.
 | 
					// GetMachineByID finds a Machine by ID and returns the Machine struct.
 | 
				
			||||||
@ -635,7 +635,7 @@ func (machine Machine) toNode(
 | 
				
			|||||||
			return nil, fmt.Errorf(
 | 
								return nil, fmt.Errorf(
 | 
				
			||||||
				"hostname %q is too long it cannot except 255 ASCII chars: %w",
 | 
									"hostname %q is too long it cannot except 255 ASCII chars: %w",
 | 
				
			||||||
				hostname,
 | 
									hostname,
 | 
				
			||||||
				errHostnameTooLong,
 | 
									ErrHostnameTooLong,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
@ -785,11 +785,11 @@ func (h *Headscale) RegisterMachineFromAuthCallback(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
			return machine, err
 | 
								return machine, err
 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			return nil, errCouldNotConvertMachineInterface
 | 
								return nil, ErrCouldNotConvertMachineInterface
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return nil, errMachineNotFoundRegistrationCache
 | 
						return nil, ErrMachineNotFoundRegistrationCache
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// RegisterMachine is executed from the CLI to register a new Machine using its MachineKey.
 | 
					// RegisterMachine is executed from the CLI to register a new Machine using its MachineKey.
 | 
				
			||||||
@ -877,7 +877,7 @@ func (h *Headscale) EnableRoutes(machine *Machine, routeStrs ...string) error {
 | 
				
			|||||||
			return fmt.Errorf(
 | 
								return fmt.Errorf(
 | 
				
			||||||
				"route (%s) is not available on node %s: %w",
 | 
									"route (%s) is not available on node %s: %w",
 | 
				
			||||||
				machine.Hostname,
 | 
									machine.Hostname,
 | 
				
			||||||
				newRoute, errMachineRouteIsNotAvailable,
 | 
									newRoute, ErrMachineRouteIsNotAvailable,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
				
			|||||||
@ -16,10 +16,10 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					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")
 | 
						ErrInvalidNamespaceName     = Error("Invalid namespace name")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
@ -47,7 +47,7 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	namespace := Namespace{}
 | 
						namespace := Namespace{}
 | 
				
			||||||
	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
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	namespace.Name = name
 | 
						namespace.Name = name
 | 
				
			||||||
	if err := h.db.Create(&namespace).Error; err != nil {
 | 
						if err := h.db.Create(&namespace).Error; err != nil {
 | 
				
			||||||
@ -67,7 +67,7 @@ func (h *Headscale) CreateNamespace(name string) (*Namespace, error) {
 | 
				
			|||||||
func (h *Headscale) DestroyNamespace(name string) error {
 | 
					func (h *Headscale) DestroyNamespace(name string) error {
 | 
				
			||||||
	namespace, err := h.GetNamespace(name)
 | 
						namespace, err := h.GetNamespace(name)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		return errNamespaceNotFound
 | 
							return ErrNamespaceNotFound
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	machines, err := h.ListMachinesInNamespace(name)
 | 
						machines, err := h.ListMachinesInNamespace(name)
 | 
				
			||||||
@ -75,7 +75,7 @@ func (h *Headscale) DestroyNamespace(name string) error {
 | 
				
			|||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if len(machines) > 0 {
 | 
						if len(machines) > 0 {
 | 
				
			||||||
		return errNamespaceNotEmptyOfNodes
 | 
							return ErrNamespaceNotEmptyOfNodes
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	keys, err := h.ListPreAuthKeys(name)
 | 
						keys, err := h.ListPreAuthKeys(name)
 | 
				
			||||||
@ -110,9 +110,9 @@ func (h *Headscale) RenameNamespace(oldName, newName string) error {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
	_, err = h.GetNamespace(newName)
 | 
						_, err = h.GetNamespace(newName)
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		return errNamespaceExists
 | 
							return ErrNamespaceExists
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if !errors.Is(err, errNamespaceNotFound) {
 | 
						if !errors.Is(err, ErrNamespaceNotFound) {
 | 
				
			||||||
		return err
 | 
							return err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -132,7 +132,7 @@ func (h *Headscale) GetNamespace(name string) (*Namespace, error) {
 | 
				
			|||||||
		result.Error,
 | 
							result.Error,
 | 
				
			||||||
		gorm.ErrRecordNotFound,
 | 
							gorm.ErrRecordNotFound,
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		return nil, errNamespaceNotFound
 | 
							return nil, ErrNamespaceNotFound
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &namespace, nil
 | 
						return &namespace, nil
 | 
				
			||||||
@ -272,7 +272,7 @@ func NormalizeToFQDNRules(name string, stripEmailDomain bool) (string, error) {
 | 
				
			|||||||
			return "", fmt.Errorf(
 | 
								return "", fmt.Errorf(
 | 
				
			||||||
				"label %v is more than 63 chars: %w",
 | 
									"label %v is more than 63 chars: %w",
 | 
				
			||||||
				elt,
 | 
									elt,
 | 
				
			||||||
				errInvalidNamespaceName,
 | 
									ErrInvalidNamespaceName,
 | 
				
			||||||
			)
 | 
								)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
@ -285,21 +285,21 @@ func CheckForFQDNRules(name string) error {
 | 
				
			|||||||
		return fmt.Errorf(
 | 
							return fmt.Errorf(
 | 
				
			||||||
			"DNS segment must not be over 63 chars. %v doesn't comply with this rule: %w",
 | 
								"DNS segment must not be over 63 chars. %v doesn't comply with this rule: %w",
 | 
				
			||||||
			name,
 | 
								name,
 | 
				
			||||||
			errInvalidNamespaceName,
 | 
								ErrInvalidNamespaceName,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if strings.ToLower(name) != name {
 | 
						if strings.ToLower(name) != name {
 | 
				
			||||||
		return fmt.Errorf(
 | 
							return fmt.Errorf(
 | 
				
			||||||
			"DNS segment should be lowercase. %v doesn't comply with this rule: %w",
 | 
								"DNS segment should be lowercase. %v doesn't comply with this rule: %w",
 | 
				
			||||||
			name,
 | 
								name,
 | 
				
			||||||
			errInvalidNamespaceName,
 | 
								ErrInvalidNamespaceName,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if invalidCharsInNamespaceRegex.MatchString(name) {
 | 
						if invalidCharsInNamespaceRegex.MatchString(name) {
 | 
				
			||||||
		return fmt.Errorf(
 | 
							return fmt.Errorf(
 | 
				
			||||||
			"DNS segment should only be composed of lowercase ASCII letters numbers, hyphen and dots. %v doesn't comply with theses rules: %w",
 | 
								"DNS segment should only be composed of lowercase ASCII letters numbers, hyphen and dots. %v doesn't comply with theses rules: %w",
 | 
				
			||||||
			name,
 | 
								name,
 | 
				
			||||||
			errInvalidNamespaceName,
 | 
								ErrInvalidNamespaceName,
 | 
				
			||||||
		)
 | 
							)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
				
			|||||||
@ -26,7 +26,7 @@ func (s *Suite) TestCreateAndDestroyNamespace(c *check.C) {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
func (s *Suite) TestDestroyNamespaceErrors(c *check.C) {
 | 
					func (s *Suite) TestDestroyNamespaceErrors(c *check.C) {
 | 
				
			||||||
	err := app.DestroyNamespace("test")
 | 
						err := app.DestroyNamespace("test")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceNotFound)
 | 
						c.Assert(err, check.Equals, ErrNamespaceNotFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace, err := app.CreateNamespace("test")
 | 
						namespace, err := app.CreateNamespace("test")
 | 
				
			||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
@ -60,7 +60,7 @@ func (s *Suite) TestDestroyNamespaceErrors(c *check.C) {
 | 
				
			|||||||
	app.db.Save(&machine)
 | 
						app.db.Save(&machine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = app.DestroyNamespace("test")
 | 
						err = app.DestroyNamespace("test")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceNotEmptyOfNodes)
 | 
						c.Assert(err, check.Equals, ErrNamespaceNotEmptyOfNodes)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Suite) TestRenameNamespace(c *check.C) {
 | 
					func (s *Suite) TestRenameNamespace(c *check.C) {
 | 
				
			||||||
@ -76,20 +76,20 @@ func (s *Suite) TestRenameNamespace(c *check.C) {
 | 
				
			|||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = app.GetNamespace("test")
 | 
						_, err = app.GetNamespace("test")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceNotFound)
 | 
						c.Assert(err, check.Equals, ErrNamespaceNotFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = app.GetNamespace("test-renamed")
 | 
						_, err = app.GetNamespace("test-renamed")
 | 
				
			||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = app.RenameNamespace("test-does-not-exit", "test")
 | 
						err = app.RenameNamespace("test-does-not-exit", "test")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceNotFound)
 | 
						c.Assert(err, check.Equals, ErrNamespaceNotFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespaceTest2, err := app.CreateNamespace("test2")
 | 
						namespaceTest2, err := app.CreateNamespace("test2")
 | 
				
			||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
	c.Assert(namespaceTest2.Name, check.Equals, "test2")
 | 
						c.Assert(namespaceTest2.Name, check.Equals, "test2")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = app.RenameNamespace("test2", "test-renamed")
 | 
						err = app.RenameNamespace("test2", "test-renamed")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceExists)
 | 
						c.Assert(err, check.Equals, ErrNamespaceExists)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
 | 
					func (s *Suite) TestGetMapResponseUserProfiles(c *check.C) {
 | 
				
			||||||
@ -402,7 +402,7 @@ func (s *Suite) TestSetMachineNamespace(c *check.C) {
 | 
				
			|||||||
	c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name)
 | 
						c.Assert(machine.Namespace.Name, check.Equals, newNamespace.Name)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = app.SetMachineNamespace(&machine, "non-existing-namespace")
 | 
						err = app.SetMachineNamespace(&machine, "non-existing-namespace")
 | 
				
			||||||
	c.Assert(err, check.Equals, errNamespaceNotFound)
 | 
						c.Assert(err, check.Equals, ErrNamespaceNotFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err = app.SetMachineNamespace(&machine, newNamespace.Name)
 | 
						err = app.SetMachineNamespace(&machine, newNamespace.Name)
 | 
				
			||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										2
									
								
								oidc.go
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								oidc.go
									
									
									
									
									
								
							@ -416,7 +416,7 @@ func (h *Headscale) OIDCCallback(
 | 
				
			|||||||
	log.Debug().Msg("Registering new machine after successful callback")
 | 
						log.Debug().Msg("Registering new machine after successful callback")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	namespace, err := h.GetNamespace(namespaceName)
 | 
						namespace, err := h.GetNamespace(namespaceName)
 | 
				
			||||||
	if errors.Is(err, errNamespaceNotFound) {
 | 
						if errors.Is(err, ErrNamespaceNotFound) {
 | 
				
			||||||
		namespace, err = h.CreateNamespace(namespaceName)
 | 
							namespace, err = h.CreateNamespace(namespaceName)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
 | 
				
			|||||||
@ -14,10 +14,10 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	errPreAuthKeyNotFound          = Error("AuthKey not found")
 | 
						ErrPreAuthKeyNotFound          = Error("AuthKey not found")
 | 
				
			||||||
	errPreAuthKeyExpired           = Error("AuthKey expired")
 | 
						ErrPreAuthKeyExpired           = Error("AuthKey expired")
 | 
				
			||||||
	errSingleUseAuthKeyHasBeenUsed = Error("AuthKey has already been used")
 | 
						ErrSingleUseAuthKeyHasBeenUsed = Error("AuthKey has already been used")
 | 
				
			||||||
	errNamespaceMismatch           = Error("namespace mismatch")
 | 
						ErrNamespaceMismatch           = Error("namespace mismatch")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// PreAuthKey describes a pre-authorization key usable in a particular namespace.
 | 
					// PreAuthKey describes a pre-authorization key usable in a particular namespace.
 | 
				
			||||||
@ -92,7 +92,7 @@ func (h *Headscale) GetPreAuthKey(namespace string, key string) (*PreAuthKey, er
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pak.Namespace.Name != namespace {
 | 
						if pak.Namespace.Name != namespace {
 | 
				
			||||||
		return nil, errNamespaceMismatch
 | 
							return nil, ErrNamespaceMismatch
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return pak, nil
 | 
						return pak, nil
 | 
				
			||||||
@ -135,11 +135,11 @@ func (h *Headscale) checkKeyValidity(k string) (*PreAuthKey, error) {
 | 
				
			|||||||
		result.Error,
 | 
							result.Error,
 | 
				
			||||||
		gorm.ErrRecordNotFound,
 | 
							gorm.ErrRecordNotFound,
 | 
				
			||||||
	) {
 | 
						) {
 | 
				
			||||||
		return nil, errPreAuthKeyNotFound
 | 
							return nil, ErrPreAuthKeyNotFound
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pak.Expiration != nil && pak.Expiration.Before(time.Now()) {
 | 
						if pak.Expiration != nil && pak.Expiration.Before(time.Now()) {
 | 
				
			||||||
		return nil, errPreAuthKeyExpired
 | 
							return nil, ErrPreAuthKeyExpired
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if pak.Reusable || pak.Ephemeral { // we don't need to check if has been used before
 | 
						if pak.Reusable || pak.Ephemeral { // we don't need to check if has been used before
 | 
				
			||||||
@ -152,7 +152,7 @@ func (h *Headscale) checkKeyValidity(k string) (*PreAuthKey, error) {
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(machines) != 0 || pak.Used {
 | 
						if len(machines) != 0 || pak.Used {
 | 
				
			||||||
		return nil, errSingleUseAuthKeyHasBeenUsed
 | 
							return nil, ErrSingleUseAuthKeyHasBeenUsed
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &pak, nil
 | 
						return &pak, nil
 | 
				
			||||||
 | 
				
			|||||||
@ -44,13 +44,13 @@ func (*Suite) TestExpiredPreAuthKey(c *check.C) {
 | 
				
			|||||||
	c.Assert(err, check.IsNil)
 | 
						c.Assert(err, check.IsNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key, err := app.checkKeyValidity(pak.Key)
 | 
						key, err := app.checkKeyValidity(pak.Key)
 | 
				
			||||||
	c.Assert(err, check.Equals, errPreAuthKeyExpired)
 | 
						c.Assert(err, check.Equals, ErrPreAuthKeyExpired)
 | 
				
			||||||
	c.Assert(key, check.IsNil)
 | 
						c.Assert(key, check.IsNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (*Suite) TestPreAuthKeyDoesNotExist(c *check.C) {
 | 
					func (*Suite) TestPreAuthKeyDoesNotExist(c *check.C) {
 | 
				
			||||||
	key, err := app.checkKeyValidity("potatoKey")
 | 
						key, err := app.checkKeyValidity("potatoKey")
 | 
				
			||||||
	c.Assert(err, check.Equals, errPreAuthKeyNotFound)
 | 
						c.Assert(err, check.Equals, ErrPreAuthKeyNotFound)
 | 
				
			||||||
	c.Assert(key, check.IsNil)
 | 
						c.Assert(key, check.IsNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -86,7 +86,7 @@ func (*Suite) TestAlreadyUsedKey(c *check.C) {
 | 
				
			|||||||
	app.db.Save(&machine)
 | 
						app.db.Save(&machine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key, err := app.checkKeyValidity(pak.Key)
 | 
						key, err := app.checkKeyValidity(pak.Key)
 | 
				
			||||||
	c.Assert(err, check.Equals, errSingleUseAuthKeyHasBeenUsed)
 | 
						c.Assert(err, check.Equals, ErrSingleUseAuthKeyHasBeenUsed)
 | 
				
			||||||
	c.Assert(key, check.IsNil)
 | 
						c.Assert(key, check.IsNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -174,7 +174,7 @@ func (*Suite) TestExpirePreauthKey(c *check.C) {
 | 
				
			|||||||
	c.Assert(pak.Expiration, check.NotNil)
 | 
						c.Assert(pak.Expiration, check.NotNil)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	key, err := app.checkKeyValidity(pak.Key)
 | 
						key, err := app.checkKeyValidity(pak.Key)
 | 
				
			||||||
	c.Assert(err, check.Equals, errPreAuthKeyExpired)
 | 
						c.Assert(err, check.Equals, ErrPreAuthKeyExpired)
 | 
				
			||||||
	c.Assert(key, check.IsNil)
 | 
						c.Assert(key, check.IsNil)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@ -188,5 +188,5 @@ func (*Suite) TestNotReusableMarkedAsUsed(c *check.C) {
 | 
				
			|||||||
	app.db.Save(&pak)
 | 
						app.db.Save(&pak)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	_, err = app.checkKeyValidity(pak.Key)
 | 
						_, err = app.checkKeyValidity(pak.Key)
 | 
				
			||||||
	c.Assert(err, check.Equals, errSingleUseAuthKeyHasBeenUsed)
 | 
						c.Assert(err, check.Equals, ErrSingleUseAuthKeyHasBeenUsed)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
@ -7,7 +7,7 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	errRouteIsNotAvailable = Error("route is not available")
 | 
						ErrRouteIsNotAvailable = Error("route is not available")
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Deprecated: use machine function instead
 | 
					// Deprecated: use machine function instead
 | 
				
			||||||
@ -106,7 +106,7 @@ func (h *Headscale) EnableNodeRoute(
 | 
				
			|||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if !available {
 | 
						if !available {
 | 
				
			||||||
		return errRouteIsNotAvailable
 | 
							return ErrRouteIsNotAvailable
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	machine.EnabledRoutes = enabledRoutes
 | 
						machine.EnabledRoutes = enabledRoutes
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										8
									
								
								utils.go
									
									
									
									
									
								
							
							
						
						
									
										8
									
								
								utils.go
									
									
									
									
									
								
							@ -27,8 +27,8 @@ import (
 | 
				
			|||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	errCannotDecryptReponse = Error("cannot decrypt response")
 | 
						ErrCannotDecryptResponse = Error("cannot decrypt response")
 | 
				
			||||||
	errCouldNotAllocateIP   = Error("could not find any suitable IP")
 | 
						ErrCouldNotAllocateIP    = Error("could not find any suitable IP")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// These constants are copied from the upstream tailscale.com/types/key
 | 
						// These constants are copied from the upstream tailscale.com/types/key
 | 
				
			||||||
	// library, because they are not exported.
 | 
						// library, because they are not exported.
 | 
				
			||||||
@ -120,7 +120,7 @@ func decode(
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	decrypted, ok := privKey.OpenFrom(*pubKey, msg)
 | 
						decrypted, ok := privKey.OpenFrom(*pubKey, msg)
 | 
				
			||||||
	if !ok {
 | 
						if !ok {
 | 
				
			||||||
		return errCannotDecryptReponse
 | 
							return ErrCannotDecryptResponse
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err := json.Unmarshal(decrypted, output); err != nil {
 | 
						if err := json.Unmarshal(decrypted, output); err != nil {
 | 
				
			||||||
@ -181,7 +181,7 @@ func (h *Headscale) getAvailableIP(ipPrefix netaddr.IPPrefix) (*netaddr.IP, erro
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	for {
 | 
						for {
 | 
				
			||||||
		if !ipPrefix.Contains(ip) {
 | 
							if !ipPrefix.Contains(ip) {
 | 
				
			||||||
			return nil, errCouldNotAllocateIP
 | 
								return nil, ErrCouldNotAllocateIP
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch {
 | 
							switch {
 | 
				
			||||||
 | 
				
			|||||||
		Loading…
	
		Reference in New Issue
	
	Block a user