mirror of
https://github.com/juanfont/headscale.git
synced 2026-11-04 20:49:24 +09:00
419 lines
11 KiB
Go
419 lines
11 KiB
Go
package cli
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/juanfont/headscale/hscontrol/db"
|
|
"github.com/juanfont/headscale/hscontrol/types"
|
|
"github.com/spf13/cobra"
|
|
"github.com/spf13/viper"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
const (
|
|
v23 = "0.23.0"
|
|
v23Alpha1 = "0.23.0-alpha.1"
|
|
v23Beta1 = "0.23.0-beta.1"
|
|
v23RC1 = "0.23.0-rc.1"
|
|
v23Dev = "0.23.0-dev"
|
|
v231 = "0.23.1"
|
|
|
|
v24Alpha1Tag = "v0.24.0-alpha.1"
|
|
v24RCTag = "v0.24.0-rc.1"
|
|
v24Tag = "v0.24.0"
|
|
)
|
|
|
|
func TestFilterPreReleasesIfStable(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
currentVersion string
|
|
tag string
|
|
expectedFilter bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "stable version filters alpha tag",
|
|
currentVersion: v23,
|
|
tag: v24Alpha1Tag,
|
|
expectedFilter: true,
|
|
description: "When on stable release, alpha tags should be filtered",
|
|
},
|
|
{
|
|
name: "stable version filters beta tag",
|
|
currentVersion: v23,
|
|
tag: "v0.24.0-beta.2",
|
|
expectedFilter: true,
|
|
description: "When on stable release, beta tags should be filtered",
|
|
},
|
|
{
|
|
name: "stable version filters rc tag",
|
|
currentVersion: v23,
|
|
tag: v24RCTag,
|
|
expectedFilter: true,
|
|
description: "When on stable release, rc tags should be filtered",
|
|
},
|
|
{
|
|
name: "stable version allows stable tag",
|
|
currentVersion: v23,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "When on stable release, stable tags should not be filtered",
|
|
},
|
|
{
|
|
name: "alpha version allows alpha tag",
|
|
currentVersion: v23Alpha1,
|
|
tag: "v0.24.0-alpha.2",
|
|
expectedFilter: false,
|
|
description: "When on alpha release, alpha tags should not be filtered",
|
|
},
|
|
{
|
|
name: "alpha version allows beta tag",
|
|
currentVersion: v23Alpha1,
|
|
tag: "v0.24.0-beta.1",
|
|
expectedFilter: false,
|
|
description: "When on alpha release, beta tags should not be filtered",
|
|
},
|
|
{
|
|
name: "alpha version allows rc tag",
|
|
currentVersion: v23Alpha1,
|
|
tag: v24RCTag,
|
|
expectedFilter: false,
|
|
description: "When on alpha release, rc tags should not be filtered",
|
|
},
|
|
{
|
|
name: "alpha version allows stable tag",
|
|
currentVersion: v23Alpha1,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "When on alpha release, stable tags should not be filtered",
|
|
},
|
|
{
|
|
name: "beta version allows alpha tag",
|
|
currentVersion: v23Beta1,
|
|
tag: v24Alpha1Tag,
|
|
expectedFilter: false,
|
|
description: "When on beta release, alpha tags should not be filtered",
|
|
},
|
|
{
|
|
name: "beta version allows beta tag",
|
|
currentVersion: "0.23.0-beta.2",
|
|
tag: "v0.24.0-beta.3",
|
|
expectedFilter: false,
|
|
description: "When on beta release, beta tags should not be filtered",
|
|
},
|
|
{
|
|
name: "beta version allows rc tag",
|
|
currentVersion: v23Beta1,
|
|
tag: v24RCTag,
|
|
expectedFilter: false,
|
|
description: "When on beta release, rc tags should not be filtered",
|
|
},
|
|
{
|
|
name: "beta version allows stable tag",
|
|
currentVersion: v23Beta1,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "When on beta release, stable tags should not be filtered",
|
|
},
|
|
{
|
|
name: "rc version allows alpha tag",
|
|
currentVersion: v23RC1,
|
|
tag: v24Alpha1Tag,
|
|
expectedFilter: false,
|
|
description: "When on rc release, alpha tags should not be filtered",
|
|
},
|
|
{
|
|
name: "rc version allows beta tag",
|
|
currentVersion: v23RC1,
|
|
tag: "v0.24.0-beta.1",
|
|
expectedFilter: false,
|
|
description: "When on rc release, beta tags should not be filtered",
|
|
},
|
|
{
|
|
name: "rc version allows rc tag",
|
|
currentVersion: "0.23.0-rc.2",
|
|
tag: "v0.24.0-rc.3",
|
|
expectedFilter: false,
|
|
description: "When on rc release, rc tags should not be filtered",
|
|
},
|
|
{
|
|
name: "rc version allows stable tag",
|
|
currentVersion: v23RC1,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "When on rc release, stable tags should not be filtered",
|
|
},
|
|
{
|
|
name: "stable version with patch filters alpha",
|
|
currentVersion: v231,
|
|
tag: v24Alpha1Tag,
|
|
expectedFilter: true,
|
|
description: "Stable version with patch number should filter alpha tags",
|
|
},
|
|
{
|
|
name: "stable version with patch allows stable",
|
|
currentVersion: v231,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "Stable version with patch number should allow stable tags",
|
|
},
|
|
{
|
|
name: "tag with alpha substring in version number",
|
|
currentVersion: v23,
|
|
tag: "v1.0.0-alpha.1",
|
|
expectedFilter: true,
|
|
description: "Tags with alpha in version string should be filtered on stable",
|
|
},
|
|
{
|
|
name: "tag with beta substring in version number",
|
|
currentVersion: v23,
|
|
tag: "v1.0.0-beta.1",
|
|
expectedFilter: true,
|
|
description: "Tags with beta in version string should be filtered on stable",
|
|
},
|
|
{
|
|
name: "tag with rc substring in version number",
|
|
currentVersion: v23,
|
|
tag: "v1.0.0-rc.1",
|
|
expectedFilter: true,
|
|
description: "Tags with rc in version string should be filtered on stable",
|
|
},
|
|
{
|
|
name: "empty tag on stable version",
|
|
currentVersion: v23,
|
|
tag: "",
|
|
expectedFilter: false,
|
|
description: "Empty tags should not be filtered",
|
|
},
|
|
{
|
|
name: "dev version allows all tags",
|
|
currentVersion: v23Dev,
|
|
tag: v24Alpha1Tag,
|
|
expectedFilter: false,
|
|
description: "Dev versions should not filter any tags (pre-release allows all)",
|
|
},
|
|
{
|
|
name: "stable version filters dev tag",
|
|
currentVersion: v23,
|
|
tag: "v0.24.0-dev",
|
|
expectedFilter: true,
|
|
description: "When on stable release, dev tags should be filtered",
|
|
},
|
|
{
|
|
name: "dev version allows dev tag",
|
|
currentVersion: v23Dev,
|
|
tag: "v0.24.0-dev.1",
|
|
expectedFilter: false,
|
|
description: "When on dev release, dev tags should not be filtered",
|
|
},
|
|
{
|
|
name: "dev version allows stable tag",
|
|
currentVersion: v23Dev,
|
|
tag: v24Tag,
|
|
expectedFilter: false,
|
|
description: "When on dev release, stable tags should not be filtered",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := filterPreReleasesIfStable(func() string { return tt.currentVersion })(tt.tag)
|
|
if result != tt.expectedFilter {
|
|
t.Errorf(
|
|
"%s: got %v, want %v\nDescription: %s\nCurrent version: %s, Tag: %s",
|
|
tt.name,
|
|
result,
|
|
tt.expectedFilter,
|
|
tt.description,
|
|
tt.currentVersion,
|
|
tt.tag,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestIsPreReleaseVersion(t *testing.T) {
|
|
tests := []struct {
|
|
name string
|
|
version string
|
|
expected bool
|
|
description string
|
|
}{
|
|
{
|
|
name: "stable version",
|
|
version: v23,
|
|
expected: false,
|
|
description: "Stable version should not be pre-release",
|
|
},
|
|
{
|
|
name: "alpha version",
|
|
version: v23Alpha1,
|
|
expected: true,
|
|
description: "Alpha version should be pre-release",
|
|
},
|
|
{
|
|
name: "beta version",
|
|
version: v23Beta1,
|
|
expected: true,
|
|
description: "Beta version should be pre-release",
|
|
},
|
|
{
|
|
name: "rc version",
|
|
version: v23RC1,
|
|
expected: true,
|
|
description: "RC version should be pre-release",
|
|
},
|
|
{
|
|
name: "version with alpha substring",
|
|
version: "0.23.0-alphabetical",
|
|
expected: true,
|
|
description: "Version containing 'alpha' should be pre-release",
|
|
},
|
|
{
|
|
name: "version with beta substring",
|
|
version: "0.23.0-betamax",
|
|
expected: true,
|
|
description: "Version containing 'beta' should be pre-release",
|
|
},
|
|
{
|
|
name: "dev version",
|
|
version: v23Dev,
|
|
expected: true,
|
|
description: "Dev version should be pre-release",
|
|
},
|
|
{
|
|
name: "empty version",
|
|
version: "",
|
|
expected: false,
|
|
description: "Empty version should not be pre-release",
|
|
},
|
|
{
|
|
name: "version with patch number",
|
|
version: v231,
|
|
expected: false,
|
|
description: "Stable version with patch should not be pre-release",
|
|
},
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
result := isPreReleaseVersion(tt.version)
|
|
if result != tt.expected {
|
|
t.Errorf(
|
|
"%s: got %v, want %v\nDescription: %s\nVersion: %s",
|
|
tt.name,
|
|
result,
|
|
tt.expected,
|
|
tt.description,
|
|
tt.version,
|
|
)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestOfflineSetPolicyRunsTests(t *testing.T) {
|
|
for _, tt := range []struct {
|
|
name string
|
|
policy string
|
|
invalid bool
|
|
}{
|
|
{
|
|
name: "passing packet test uses database nodes",
|
|
policy: `{
|
|
"acls": [{"action":"accept","src":["alice@"],"dst":["bob@:22"]}],
|
|
"tests": [{"src":"alice@","accept":["bob@:22"]}]
|
|
}`,
|
|
},
|
|
{
|
|
name: "failing packet test preserves stored policy",
|
|
policy: `{
|
|
"acls": [],
|
|
"tests": [{"src":"alice@","accept":["bob@:22"]}]
|
|
}`,
|
|
invalid: true,
|
|
},
|
|
{
|
|
name: "failing SSH test preserves stored policy",
|
|
policy: `{
|
|
"acls": [{"action":"accept","src":["*"],"dst":["*:*"]}],
|
|
"ssh": [{"action":"accept","src":["alice@"],"dst":["autogroup:member"],"users":["root"]}],
|
|
"sshTests": [{"src":"bob@","dst":["autogroup:member"],"accept":["root"]}]
|
|
}`,
|
|
invalid: true,
|
|
},
|
|
} {
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
viper.Reset()
|
|
t.Cleanup(viper.Reset)
|
|
|
|
dir := t.TempDir()
|
|
configPath := filepath.Join(dir, "config.yaml")
|
|
config := fmt.Sprintf(`server_url: https://headscale.example.com
|
|
noise:
|
|
private_key_path: noise_private.key
|
|
prefixes:
|
|
v4: 100.64.0.0/10
|
|
database:
|
|
type: sqlite3
|
|
sqlite:
|
|
path: %q
|
|
policy:
|
|
mode: database
|
|
dns:
|
|
magic_dns: false
|
|
override_local_dns: false
|
|
`, filepath.Join(dir, "headscale.db"))
|
|
require.NoError(t, os.WriteFile(configPath, []byte(config), 0o600))
|
|
require.NoError(t, types.LoadConfig(configPath, true))
|
|
|
|
cfg, err := types.LoadServerConfig()
|
|
require.NoError(t, err)
|
|
|
|
database, err := db.NewHeadscaleDatabase(cfg)
|
|
require.NoError(t, err)
|
|
|
|
t.Cleanup(func() { _ = database.Close() })
|
|
|
|
for _, name := range []string{"alice", "bob"} {
|
|
user := database.CreateUserForTest(name)
|
|
database.CreateRegisteredNodeForTest(user, name+"-node")
|
|
}
|
|
|
|
const oldPolicy = `{"acls":[{"action":"accept","src":["*"],"dst":["*:*"]}]}`
|
|
|
|
before, err := database.SetPolicy(oldPolicy)
|
|
require.NoError(t, err)
|
|
|
|
path := filepath.Join(dir, "policy.hujson")
|
|
require.NoError(t, os.WriteFile(path, []byte(tt.policy), 0o600))
|
|
|
|
cmd := &cobra.Command{}
|
|
cmd.Flags().String("file", path, "")
|
|
cmd.Flags().Bool(bypassFlag, true, "")
|
|
cmd.Flags().Bool("force", true, "")
|
|
|
|
err = setPolicy.RunE(cmd, nil)
|
|
if tt.invalid {
|
|
require.ErrorContains(t, err, "test(s) failed")
|
|
} else {
|
|
require.NoError(t, err)
|
|
}
|
|
|
|
after, err := database.GetPolicy()
|
|
require.NoError(t, err)
|
|
|
|
if tt.invalid {
|
|
require.Equal(t, before.ID, after.ID)
|
|
require.JSONEq(t, oldPolicy, after.Data)
|
|
} else {
|
|
require.JSONEq(t, tt.policy, after.Data)
|
|
}
|
|
})
|
|
}
|
|
}
|