policy: remove v1 code (#2600)
* policy: remove v1 code Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * db: update test with v1 removal Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * integration: start moving to v2 policy Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * policy: add ssh unmarshal tests Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * changelog: add entry Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * policy: remove v1 comment Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * integration: remove comment out case Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * cleanup skipv1 Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * policy: remove v1 prefix workaround Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> * policy: add all node ips if prefix/host is ts ip Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com> --------- Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
1605e2a7a9
commit
a52f1df180
21 changed files with 1258 additions and 4837 deletions
|
@ -7,50 +7,53 @@ import (
|
|||
"testing"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
var veryLargeDestination = []string{
|
||||
"0.0.0.0/5:*",
|
||||
"8.0.0.0/7:*",
|
||||
"11.0.0.0/8:*",
|
||||
"12.0.0.0/6:*",
|
||||
"16.0.0.0/4:*",
|
||||
"32.0.0.0/3:*",
|
||||
"64.0.0.0/2:*",
|
||||
"128.0.0.0/3:*",
|
||||
"160.0.0.0/5:*",
|
||||
"168.0.0.0/6:*",
|
||||
"172.0.0.0/12:*",
|
||||
"172.32.0.0/11:*",
|
||||
"172.64.0.0/10:*",
|
||||
"172.128.0.0/9:*",
|
||||
"173.0.0.0/8:*",
|
||||
"174.0.0.0/7:*",
|
||||
"176.0.0.0/4:*",
|
||||
"192.0.0.0/9:*",
|
||||
"192.128.0.0/11:*",
|
||||
"192.160.0.0/13:*",
|
||||
"192.169.0.0/16:*",
|
||||
"192.170.0.0/15:*",
|
||||
"192.172.0.0/14:*",
|
||||
"192.176.0.0/12:*",
|
||||
"192.192.0.0/10:*",
|
||||
"193.0.0.0/8:*",
|
||||
"194.0.0.0/7:*",
|
||||
"196.0.0.0/6:*",
|
||||
"200.0.0.0/5:*",
|
||||
"208.0.0.0/4:*",
|
||||
var veryLargeDestination = []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp("0.0.0.0/5"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("8.0.0.0/7"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("11.0.0.0/8"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("12.0.0.0/6"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("16.0.0.0/4"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("32.0.0.0/3"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("64.0.0.0/2"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("128.0.0.0/3"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("160.0.0.0/5"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("168.0.0.0/6"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("172.0.0.0/12"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("172.32.0.0/11"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("172.64.0.0/10"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("172.128.0.0/9"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("173.0.0.0/8"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("174.0.0.0/7"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("176.0.0.0/4"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.0.0.0/9"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.128.0.0/11"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.160.0.0/13"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.169.0.0/16"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.170.0.0/15"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.172.0.0/14"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.176.0.0/12"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("192.192.0.0/10"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("193.0.0.0/8"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("194.0.0.0/7"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("196.0.0.0/6"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("200.0.0.0/5"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("208.0.0.0/4"), tailcfg.PortRangeAny),
|
||||
}
|
||||
|
||||
func aclScenario(
|
||||
t *testing.T,
|
||||
policy *policyv1.ACLPolicy,
|
||||
policy *policyv2.Policy,
|
||||
clientsPerUser int,
|
||||
) *Scenario {
|
||||
t.Helper()
|
||||
|
@ -108,19 +111,21 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
// they can access minus one (them self).
|
||||
tests := map[string]struct {
|
||||
users ScenarioSpec
|
||||
policy policyv1.ACLPolicy
|
||||
policy policyv2.Policy
|
||||
want map[string]int
|
||||
}{
|
||||
// Test that when we have no ACL, each client netmap has
|
||||
// the amount of peers of the total amount of clients
|
||||
"base-acls": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -133,17 +138,21 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
// their own user.
|
||||
"two-isolated-users": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user1@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user1@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user2@"},
|
||||
Destinations: []string{"user2@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user2@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -156,27 +165,35 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
// in the netmap.
|
||||
"two-restricted-present-in-netmap": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user1@:22"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user1@"), tailcfg.PortRange{First: 22, Last: 22}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user2@"},
|
||||
Destinations: []string{"user2@:22"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user2@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRange{First: 22, Last: 22}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user2@:22"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRange{First: 22, Last: 22}),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user2@"},
|
||||
Destinations: []string{"user1@:22"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user2@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user1@"), tailcfg.PortRange{First: 22, Last: 22}),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -190,22 +207,28 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
// need them present on the other side for the "return path".
|
||||
"two-ns-one-isolated": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user1@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user1@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user2@"},
|
||||
Destinations: []string{"user2@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user2@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user2@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -215,22 +238,37 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
},
|
||||
"very-large-destination-prefix-1372": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: append([]string{"user1@:*"}, veryLargeDestination...),
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: append(
|
||||
[]policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user1@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
veryLargeDestination...,
|
||||
),
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user2@"},
|
||||
Destinations: append([]string{"user2@:*"}, veryLargeDestination...),
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user2@")},
|
||||
Destinations: append(
|
||||
[]policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
veryLargeDestination...,
|
||||
),
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: append([]string{"user2@:*"}, veryLargeDestination...),
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: append(
|
||||
[]policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
veryLargeDestination...,
|
||||
),
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -240,12 +278,15 @@ func TestACLHostsInNetMapTable(t *testing.T) {
|
|||
},
|
||||
"ipv6-acls-1470": {
|
||||
users: spec,
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"0.0.0.0/0:*", "::/0:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp("0.0.0.0/0"), tailcfg.PortRangeAny),
|
||||
aliasWithPorts(prefixp("::/0"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
}, want: map[string]int{
|
||||
|
@ -295,12 +336,14 @@ func TestACLAllowUser80Dst(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user2@:80"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRange{First: 80, Last: 80}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -349,15 +392,17 @@ func TestACLDenyAllPort80(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:integration-acl-test": {"user1@", "user2@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:integration-acl-test"): []policyv2.Username{policyv2.Username("user1@"), policyv2.Username("user2@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:integration-acl-test"},
|
||||
Destinations: []string{"*:22"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{groupp("group:integration-acl-test")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRange{First: 22, Last: 22}),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -396,12 +441,14 @@ func TestACLAllowUserDst(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user2@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -452,12 +499,14 @@ func TestACLAllowStarDst(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -509,16 +558,18 @@ func TestACLNamedHostsCanReachBySubnet(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Hosts: policyv1.Hosts{
|
||||
"all": netip.MustParsePrefix("100.64.0.0/24"),
|
||||
&policyv2.Policy{
|
||||
Hosts: policyv2.Hosts{
|
||||
"all": policyv2.Prefix(netip.MustParsePrefix("100.64.0.0/24")),
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
// Everyone can curl test3
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"all:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("all"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -606,50 +657,58 @@ func TestACLNamedHostsCanReach(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
tests := map[string]struct {
|
||||
policy policyv1.ACLPolicy
|
||||
policy policyv2.Policy
|
||||
}{
|
||||
"ipv4": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
Hosts: policyv1.Hosts{
|
||||
"test1": netip.MustParsePrefix("100.64.0.1/32"),
|
||||
"test2": netip.MustParsePrefix("100.64.0.2/32"),
|
||||
"test3": netip.MustParsePrefix("100.64.0.3/32"),
|
||||
policy: policyv2.Policy{
|
||||
Hosts: policyv2.Hosts{
|
||||
"test1": policyv2.Prefix(netip.MustParsePrefix("100.64.0.1/32")),
|
||||
"test2": policyv2.Prefix(netip.MustParsePrefix("100.64.0.2/32")),
|
||||
"test3": policyv2.Prefix(netip.MustParsePrefix("100.64.0.3/32")),
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
// Everyone can curl test3
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"test3:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test3"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
// test1 can curl test2
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"test1"},
|
||||
Destinations: []string{"test2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{hostp("test1")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test2"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ipv6": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
Hosts: policyv1.Hosts{
|
||||
"test1": netip.MustParsePrefix("fd7a:115c:a1e0::1/128"),
|
||||
"test2": netip.MustParsePrefix("fd7a:115c:a1e0::2/128"),
|
||||
"test3": netip.MustParsePrefix("fd7a:115c:a1e0::3/128"),
|
||||
policy: policyv2.Policy{
|
||||
Hosts: policyv2.Hosts{
|
||||
"test1": policyv2.Prefix(netip.MustParsePrefix("fd7a:115c:a1e0::1/128")),
|
||||
"test2": policyv2.Prefix(netip.MustParsePrefix("fd7a:115c:a1e0::2/128")),
|
||||
"test3": policyv2.Prefix(netip.MustParsePrefix("fd7a:115c:a1e0::3/128")),
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
// Everyone can curl test3
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"test3:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test3"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
// test1 can curl test2
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"test1"},
|
||||
Destinations: []string{"test2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{hostp("test1")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test2"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -855,71 +914,81 @@ func TestACLDevice1CanAccessDevice2(t *testing.T) {
|
|||
IntegrationSkip(t)
|
||||
|
||||
tests := map[string]struct {
|
||||
policy policyv1.ACLPolicy
|
||||
policy policyv2.Policy
|
||||
}{
|
||||
"ipv4": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"100.64.0.1"},
|
||||
Destinations: []string{"100.64.0.2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{prefixp("100.64.0.1/32")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp("100.64.0.2/32"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"ipv6": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"fd7a:115c:a1e0::1"},
|
||||
Destinations: []string{"fd7a:115c:a1e0::2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{prefixp("fd7a:115c:a1e0::1/128")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp("fd7a:115c:a1e0::2/128"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"hostv4cidr": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
Hosts: policyv1.Hosts{
|
||||
"test1": netip.MustParsePrefix("100.64.0.1/32"),
|
||||
"test2": netip.MustParsePrefix("100.64.0.2/32"),
|
||||
policy: policyv2.Policy{
|
||||
Hosts: policyv2.Hosts{
|
||||
"test1": policyv2.Prefix(netip.MustParsePrefix("100.64.0.1/32")),
|
||||
"test2": policyv2.Prefix(netip.MustParsePrefix("100.64.0.2/32")),
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"test1"},
|
||||
Destinations: []string{"test2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{hostp("test1")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test2"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"hostv6cidr": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
Hosts: policyv1.Hosts{
|
||||
"test1": netip.MustParsePrefix("fd7a:115c:a1e0::1/128"),
|
||||
"test2": netip.MustParsePrefix("fd7a:115c:a1e0::2/128"),
|
||||
policy: policyv2.Policy{
|
||||
Hosts: policyv2.Hosts{
|
||||
"test1": policyv2.Prefix(netip.MustParsePrefix("fd7a:115c:a1e0::1/128")),
|
||||
"test2": policyv2.Prefix(netip.MustParsePrefix("fd7a:115c:a1e0::2/128")),
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"test1"},
|
||||
Destinations: []string{"test2:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{hostp("test1")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(hostp("test2"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"group": {
|
||||
policy: policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:one": {"user1@"},
|
||||
"group:two": {"user2@"},
|
||||
policy: policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:one"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
policyv2.Group("group:two"): []policyv2.Username{policyv2.Username("user2@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:one"},
|
||||
Destinations: []string{"group:two:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{groupp("group:one")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(groupp("group:two"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1073,15 +1142,17 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
|
|||
headscale, err := scenario.Headscale()
|
||||
require.NoError(t, err)
|
||||
|
||||
p := policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
p := policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"user1@"},
|
||||
Destinations: []string{"user2@:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{usernamep("user1@")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(usernamep("user2@"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
Hosts: policyv1.Hosts{},
|
||||
Hosts: policyv2.Hosts{},
|
||||
}
|
||||
|
||||
err = headscale.SetPolicy(&p)
|
||||
|
@ -1089,7 +1160,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
|
|||
|
||||
// Get the current policy and check
|
||||
// if it is the same as the one we set.
|
||||
var output *policyv1.ACLPolicy
|
||||
var output *policyv2.Policy
|
||||
err = executeAndUnmarshal(
|
||||
headscale,
|
||||
[]string{
|
||||
|
@ -1105,7 +1176,7 @@ func TestPolicyUpdateWhileRunningWithCLIInDatabase(t *testing.T) {
|
|||
|
||||
assert.Len(t, output.ACLs, 1)
|
||||
|
||||
if diff := cmp.Diff(p, *output); diff != "" {
|
||||
if diff := cmp.Diff(p, *output, cmpopts.IgnoreUnexported(policyv2.Policy{}), cmpopts.EquateEmpty()); diff != "" {
|
||||
t.Errorf("unexpected policy(-want +got):\n%s", diff)
|
||||
}
|
||||
|
||||
|
@ -1145,12 +1216,14 @@ func TestACLAutogroupMember(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"autogroup:member"},
|
||||
Destinations: []string{"autogroup:member:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupMember)},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(ptr.To(policyv2.AutoGroupMember), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -1201,15 +1274,18 @@ func TestACLAutogroupTagged(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := aclScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
&policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"autogroup:tagged"},
|
||||
Destinations: []string{"autogroup:tagged:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{ptr.To(policyv2.AutoGroupTagged)},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(ptr.To(policyv2.AutoGroupTagged), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
2,
|
||||
)
|
||||
defer scenario.ShutdownAssertNoPanics(t)
|
||||
|
|
|
@ -12,12 +12,13 @@ import (
|
|||
tcmp "github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/tailcfg"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
|
@ -912,13 +913,15 @@ func TestNodeTagCommand(t *testing.T) {
|
|||
)
|
||||
}
|
||||
|
||||
|
||||
|
||||
func TestNodeAdvertiseTagCommand(t *testing.T) {
|
||||
IntegrationSkip(t)
|
||||
t.Parallel()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
policy *policyv1.ACLPolicy
|
||||
policy *policyv2.Policy
|
||||
wantTag bool
|
||||
}{
|
||||
{
|
||||
|
@ -927,51 +930,60 @@ func TestNodeAdvertiseTagCommand(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "with-policy-email",
|
||||
policy: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:test": {"user1@test.no"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:test"): policyv2.Owners{usernameOwner("user1@test.no")},
|
||||
},
|
||||
},
|
||||
wantTag: true,
|
||||
},
|
||||
{
|
||||
name: "with-policy-username",
|
||||
policy: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
policy: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:test": {"user1@"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:test"): policyv2.Owners{usernameOwner("user1@")},
|
||||
},
|
||||
},
|
||||
wantTag: true,
|
||||
},
|
||||
{
|
||||
name: "with-policy-groups",
|
||||
policy: &policyv1.ACLPolicy{
|
||||
Groups: policyv1.Groups{
|
||||
"group:admins": []string{"user1@"},
|
||||
policy: &policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:admins"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:test": {"group:admins"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:test"): policyv2.Owners{groupOwner("group:admins")},
|
||||
},
|
||||
},
|
||||
wantTag: true,
|
||||
|
@ -1746,16 +1758,19 @@ func TestPolicyCommand(t *testing.T) {
|
|||
headscale, err := scenario.Headscale()
|
||||
assertNoErr(t, err)
|
||||
|
||||
p := policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
p := policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:exists": {"user1@"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:exists"): policyv2.Owners{usernameOwner("user1@")},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -1782,7 +1797,7 @@ func TestPolicyCommand(t *testing.T) {
|
|||
|
||||
// Get the current policy and check
|
||||
// if it is the same as the one we set.
|
||||
var output *policyv1.ACLPolicy
|
||||
var output *policyv2.Policy
|
||||
err = executeAndUnmarshal(
|
||||
headscale,
|
||||
[]string{
|
||||
|
@ -1825,18 +1840,21 @@ func TestPolicyBrokenConfigCommand(t *testing.T) {
|
|||
headscale, err := scenario.Headscale()
|
||||
assertNoErr(t, err)
|
||||
|
||||
p := policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
p := policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
// This is an unknown action, so it will return an error
|
||||
// and the config will not be applied.
|
||||
Action: "unknown-action",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "unknown-action",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:exists": {"user1@"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:exists"): policyv2.Owners{usernameOwner("user1@")},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import (
|
|||
"net/netip"
|
||||
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/ory/dockertest/v3"
|
||||
)
|
||||
|
||||
|
@ -28,5 +28,5 @@ type ControlServer interface {
|
|||
ApproveRoutes(uint64, []netip.Prefix) (*v1.Node, error)
|
||||
GetCert() []byte
|
||||
GetHostname() string
|
||||
SetPolicy(*policyv1.ACLPolicy) error
|
||||
SetPolicy(*policyv2.Policy) error
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import (
|
|||
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/integration/dockertestutil"
|
||||
|
@ -65,7 +65,7 @@ type HeadscaleInContainer struct {
|
|||
extraPorts []string
|
||||
caCerts [][]byte
|
||||
hostPortBindings map[string][]string
|
||||
aclPolicy *policyv1.ACLPolicy
|
||||
aclPolicy *policyv2.Policy
|
||||
env map[string]string
|
||||
tlsCert []byte
|
||||
tlsKey []byte
|
||||
|
@ -80,7 +80,7 @@ type Option = func(c *HeadscaleInContainer)
|
|||
|
||||
// WithACLPolicy adds a hscontrol.ACLPolicy policy to the
|
||||
// HeadscaleInContainer instance.
|
||||
func WithACLPolicy(acl *policyv1.ACLPolicy) Option {
|
||||
func WithACLPolicy(acl *policyv2.Policy) Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
if acl == nil {
|
||||
return
|
||||
|
@ -188,13 +188,6 @@ func WithPostgres() Option {
|
|||
}
|
||||
}
|
||||
|
||||
// WithPolicyV1 tells the integration test to use the old v1 filter.
|
||||
func WithPolicyV1() Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
hsic.env["HEADSCALE_POLICY_V1"] = "1"
|
||||
}
|
||||
}
|
||||
|
||||
// WithPolicy sets the policy mode for headscale
|
||||
func WithPolicyMode(mode types.PolicyMode) Option {
|
||||
return func(hsic *HeadscaleInContainer) {
|
||||
|
@ -889,7 +882,7 @@ func (t *HeadscaleInContainer) MapUsers() (map[string]*v1.User, error) {
|
|||
return userMap, nil
|
||||
}
|
||||
|
||||
func (h *HeadscaleInContainer) SetPolicy(pol *policyv1.ACLPolicy) error {
|
||||
func (h *HeadscaleInContainer) SetPolicy(pol *policyv2.Policy) error {
|
||||
err := h.writePolicy(pol)
|
||||
if err != nil {
|
||||
return fmt.Errorf("writing policy file: %w", err)
|
||||
|
@ -930,7 +923,7 @@ func (h *HeadscaleInContainer) reloadDatabasePolicy() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (h *HeadscaleInContainer) writePolicy(pol *policyv1.ACLPolicy) error {
|
||||
func (h *HeadscaleInContainer) writePolicy(pol *policyv2.Policy) error {
|
||||
pBytes, err := json.Marshal(pol)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshalling pol: %w", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"fmt"
|
||||
"net/netip"
|
||||
"sort"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
|
@ -13,7 +14,7 @@ import (
|
|||
cmpdiff "github.com/google/go-cmp/cmp"
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
v1 "github.com/juanfont/headscale/gen/go/headscale/v1"
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/types"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
|
@ -22,6 +23,7 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
"tailscale.com/ipn/ipnstate"
|
||||
"tailscale.com/net/tsaddr"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/ipproto"
|
||||
"tailscale.com/types/views"
|
||||
"tailscale.com/util/must"
|
||||
|
@ -793,26 +795,25 @@ func TestSubnetRouteACL(t *testing.T) {
|
|||
err = scenario.CreateHeadscaleEnv([]tsic.Option{
|
||||
tsic.WithAcceptRoutes(),
|
||||
}, hsic.WithTestName("clienableroute"), hsic.WithACLPolicy(
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: policyv1.Groups{
|
||||
"group:admins": {user + "@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:admins"): []policyv2.Username{policyv2.Username(user + "@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:admins"},
|
||||
Destinations: []string{"group:admins:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{groupp("group:admins")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(groupp("group:admins"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:admins"},
|
||||
Destinations: []string{"10.33.0.0/16:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{groupp("group:admins")},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp("10.33.0.0/16"), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
// {
|
||||
// Action: "accept",
|
||||
// Sources: []string{"group:admins"},
|
||||
// Destinations: []string{"0.0.0.0/0:*"},
|
||||
// },
|
||||
},
|
||||
},
|
||||
))
|
||||
|
@ -1384,29 +1385,31 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
|
||||
tests := []struct {
|
||||
name string
|
||||
pol *policyv1.ACLPolicy
|
||||
pol *policyv2.Policy
|
||||
approver string
|
||||
spec ScenarioSpec
|
||||
withURL bool
|
||||
}{
|
||||
{
|
||||
name: "authkey-tag",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:approve": {"user1@"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:approve"): policyv2.Owners{usernameOwner("user1@")},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"tag:approve"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {tagApprover("tag:approve")},
|
||||
},
|
||||
ExitNode: []string{"tag:approve"},
|
||||
ExitNode: policyv2.AutoApprovers{tagApprover("tag:approve")},
|
||||
},
|
||||
},
|
||||
approver: "tag:approve",
|
||||
|
@ -1427,19 +1430,21 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "authkey-user",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"user1@"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {usernameApprover("user1@")},
|
||||
},
|
||||
ExitNode: []string{"user1@"},
|
||||
ExitNode: policyv2.AutoApprovers{usernameApprover("user1@")},
|
||||
},
|
||||
},
|
||||
approver: "user1@",
|
||||
|
@ -1460,22 +1465,24 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "authkey-group",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
Groups: policyv1.Groups{
|
||||
"group:approve": []string{"user1@"},
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:approve"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"group:approve"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {groupApprover("group:approve")},
|
||||
},
|
||||
ExitNode: []string{"group:approve"},
|
||||
ExitNode: policyv2.AutoApprovers{groupApprover("group:approve")},
|
||||
},
|
||||
},
|
||||
approver: "group:approve",
|
||||
|
@ -1496,19 +1503,21 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "webauth-user",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"user1@"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {usernameApprover("user1@")},
|
||||
},
|
||||
ExitNode: []string{"user1@"},
|
||||
ExitNode: policyv2.AutoApprovers{usernameApprover("user1@")},
|
||||
},
|
||||
},
|
||||
approver: "user1@",
|
||||
|
@ -1530,22 +1539,24 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "webauth-tag",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
TagOwners: map[string][]string{
|
||||
"tag:approve": {"user1@"},
|
||||
TagOwners: policyv2.TagOwners{
|
||||
policyv2.Tag("tag:approve"): policyv2.Owners{usernameOwner("user1@")},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"tag:approve"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {tagApprover("tag:approve")},
|
||||
},
|
||||
ExitNode: []string{"tag:approve"},
|
||||
ExitNode: policyv2.AutoApprovers{tagApprover("tag:approve")},
|
||||
},
|
||||
},
|
||||
approver: "tag:approve",
|
||||
|
@ -1567,22 +1578,24 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
},
|
||||
{
|
||||
name: "webauth-group",
|
||||
pol: &policyv1.ACLPolicy{
|
||||
ACLs: []policyv1.ACL{
|
||||
pol: &policyv2.Policy{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
Groups: policyv1.Groups{
|
||||
"group:approve": []string{"user1@"},
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:approve"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
AutoApprovers: policyv1.AutoApprovers{
|
||||
Routes: map[string][]string{
|
||||
bigRoute.String(): {"group:approve"},
|
||||
AutoApprovers: policyv2.AutoApproverPolicy{
|
||||
Routes: map[netip.Prefix]policyv2.AutoApprovers{
|
||||
bigRoute: {groupApprover("group:approve")},
|
||||
},
|
||||
ExitNode: []string{"group:approve"},
|
||||
ExitNode: policyv2.AutoApprovers{groupApprover("group:approve")},
|
||||
},
|
||||
},
|
||||
approver: "group:approve",
|
||||
|
@ -1657,7 +1670,20 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
assert.NotNil(t, headscale)
|
||||
|
||||
// Set the route of usernet1 to be autoapproved
|
||||
tt.pol.AutoApprovers.Routes[route.String()] = []string{tt.approver}
|
||||
var approvers policyv2.AutoApprovers
|
||||
switch {
|
||||
case strings.HasPrefix(tt.approver, "tag:"):
|
||||
approvers = append(approvers, tagApprover(tt.approver))
|
||||
case strings.HasPrefix(tt.approver, "group:"):
|
||||
approvers = append(approvers, groupApprover(tt.approver))
|
||||
default:
|
||||
approvers = append(approvers, usernameApprover(tt.approver))
|
||||
}
|
||||
if tt.pol.AutoApprovers.Routes == nil {
|
||||
tt.pol.AutoApprovers.Routes = make(map[netip.Prefix]policyv2.AutoApprovers)
|
||||
}
|
||||
prefix := *route
|
||||
tt.pol.AutoApprovers.Routes[prefix] = approvers
|
||||
err = headscale.SetPolicy(tt.pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1767,7 +1793,8 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
assertTracerouteViaIP(t, tr, routerUsernet1.MustIPv4())
|
||||
|
||||
// Remove the auto approval from the policy, any routes already enabled should be allowed.
|
||||
delete(tt.pol.AutoApprovers.Routes, route.String())
|
||||
prefix = *route
|
||||
delete(tt.pol.AutoApprovers.Routes, prefix)
|
||||
err = headscale.SetPolicy(tt.pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -1831,7 +1858,20 @@ func TestAutoApproveMultiNetwork(t *testing.T) {
|
|||
|
||||
// Add the route back to the auto approver in the policy, the route should
|
||||
// now become available again.
|
||||
tt.pol.AutoApprovers.Routes[route.String()] = []string{tt.approver}
|
||||
var newApprovers policyv2.AutoApprovers
|
||||
switch {
|
||||
case strings.HasPrefix(tt.approver, "tag:"):
|
||||
newApprovers = append(newApprovers, tagApprover(tt.approver))
|
||||
case strings.HasPrefix(tt.approver, "group:"):
|
||||
newApprovers = append(newApprovers, groupApprover(tt.approver))
|
||||
default:
|
||||
newApprovers = append(newApprovers, usernameApprover(tt.approver))
|
||||
}
|
||||
if tt.pol.AutoApprovers.Routes == nil {
|
||||
tt.pol.AutoApprovers.Routes = make(map[netip.Prefix]policyv2.AutoApprovers)
|
||||
}
|
||||
prefix = *route
|
||||
tt.pol.AutoApprovers.Routes[prefix] = newApprovers
|
||||
err = headscale.SetPolicy(tt.pol)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -2070,7 +2110,9 @@ func TestSubnetRouteACLFiltering(t *testing.T) {
|
|||
"src": [
|
||||
"node"
|
||||
],
|
||||
"dst": []
|
||||
"dst": [
|
||||
"*:*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}`)
|
||||
|
@ -2090,8 +2132,7 @@ func TestSubnetRouteACLFiltering(t *testing.T) {
|
|||
weburl := fmt.Sprintf("http://%s/etc/hostname", webip)
|
||||
t.Logf("webservice: %s, %s", webip.String(), weburl)
|
||||
|
||||
// Create ACL policy
|
||||
aclPolicy := &policyv1.ACLPolicy{}
|
||||
aclPolicy := &policyv2.Policy{}
|
||||
err = json.Unmarshal([]byte(aclPolicyStr), aclPolicy)
|
||||
require.NoError(t, err)
|
||||
|
||||
|
@ -2121,24 +2162,23 @@ func TestSubnetRouteACLFiltering(t *testing.T) {
|
|||
routerClient := allClients[0]
|
||||
nodeClient := allClients[1]
|
||||
|
||||
aclPolicy.Hosts = policyv1.Hosts{
|
||||
routerUser: must.Get(routerClient.MustIPv4().Prefix(32)),
|
||||
nodeUser: must.Get(nodeClient.MustIPv4().Prefix(32)),
|
||||
aclPolicy.Hosts = policyv2.Hosts{
|
||||
policyv2.Host(routerUser): policyv2.Prefix(must.Get(routerClient.MustIPv4().Prefix(32))),
|
||||
policyv2.Host(nodeUser): policyv2.Prefix(must.Get(nodeClient.MustIPv4().Prefix(32))),
|
||||
}
|
||||
aclPolicy.ACLs[1].Destinations = []string{
|
||||
route.String() + ":*",
|
||||
aclPolicy.ACLs[1].Destinations = []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(prefixp(route.String()), tailcfg.PortRangeAny),
|
||||
}
|
||||
|
||||
require.NoError(t, headscale.SetPolicy(aclPolicy))
|
||||
|
||||
// Set up the subnet routes for the router
|
||||
routes := []string{
|
||||
route.String(), // This should be accessible by the client
|
||||
"10.10.11.0/24", // These should NOT be accessible
|
||||
"10.10.12.0/24",
|
||||
routes := []netip.Prefix{
|
||||
*route, // This should be accessible by the client
|
||||
netip.MustParsePrefix("10.10.11.0/24"), // These should NOT be accessible
|
||||
netip.MustParsePrefix("10.10.12.0/24"),
|
||||
}
|
||||
|
||||
routeArg := "--advertise-routes=" + routes[0] + "," + routes[1] + "," + routes[2]
|
||||
routeArg := "--advertise-routes=" + routes[0].String() + "," + routes[1].String() + "," + routes[2].String()
|
||||
command := []string{
|
||||
"tailscale",
|
||||
"set",
|
||||
|
@ -2208,5 +2248,4 @@ func TestSubnetRouteACLFiltering(t *testing.T) {
|
|||
tr, err := nodeClient.Traceroute(webip)
|
||||
require.NoError(t, err)
|
||||
assertTracerouteViaIP(t, tr, routerClient.MustIPv4())
|
||||
|
||||
}
|
||||
|
|
|
@ -47,7 +47,6 @@ const (
|
|||
)
|
||||
|
||||
var usePostgresForTest = envknob.Bool("HEADSCALE_INTEGRATION_POSTGRES")
|
||||
var usePolicyV1ForTest = envknob.Bool("HEADSCALE_POLICY_V1")
|
||||
|
||||
var (
|
||||
errNoHeadscaleAvailable = errors.New("no headscale available")
|
||||
|
@ -414,10 +413,6 @@ func (s *Scenario) Headscale(opts ...hsic.Option) (ControlServer, error) {
|
|||
opts = append(opts, hsic.WithPostgres())
|
||||
}
|
||||
|
||||
if usePolicyV1ForTest {
|
||||
opts = append(opts, hsic.WithPolicyV1())
|
||||
}
|
||||
|
||||
headscale, err := hsic.New(s.pool, s.Networks(), opts...)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to create headscale container: %w", err)
|
||||
|
|
|
@ -7,10 +7,11 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
policyv1 "github.com/juanfont/headscale/hscontrol/policy/v1"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/integration/hsic"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"tailscale.com/tailcfg"
|
||||
)
|
||||
|
||||
func isSSHNoAccessStdError(stderr string) bool {
|
||||
|
@ -48,7 +49,7 @@ var retry = func(times int, sleepInterval time.Duration,
|
|||
return result, stderr, err
|
||||
}
|
||||
|
||||
func sshScenario(t *testing.T, policy *policyv1.ACLPolicy, clientsPerUser int) *Scenario {
|
||||
func sshScenario(t *testing.T, policy *policyv2.Policy, clientsPerUser int) *Scenario {
|
||||
t.Helper()
|
||||
|
||||
spec := ScenarioSpec{
|
||||
|
@ -92,23 +93,26 @@ func TestSSHOneUserToAll(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := sshScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:integration-test": {"user1@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:integration-test"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
SSHs: []policyv1.SSH{
|
||||
SSHs: []policyv2.SSH{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:integration-test"},
|
||||
Destinations: []string{"*"},
|
||||
Users: []string{"ssh-it-user"},
|
||||
Sources: policyv2.SSHSrcAliases{groupp("group:integration-test")},
|
||||
Destinations: policyv2.SSHDstAliases{wildcard()},
|
||||
Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -157,23 +161,26 @@ func TestSSHMultipleUsersAllToAll(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := sshScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:integration-test": {"user1@", "user2@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:integration-test"): []policyv2.Username{policyv2.Username("user1@"), policyv2.Username("user2@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
SSHs: []policyv1.SSH{
|
||||
SSHs: []policyv2.SSH{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:integration-test"},
|
||||
Destinations: []string{"user1@", "user2@"},
|
||||
Users: []string{"ssh-it-user"},
|
||||
Sources: policyv2.SSHSrcAliases{groupp("group:integration-test")},
|
||||
Destinations: policyv2.SSHDstAliases{usernamep("user1@"), usernamep("user2@")},
|
||||
Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -210,18 +217,21 @@ func TestSSHNoSSHConfigured(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := sshScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:integration-test": {"user1@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:integration-test"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
SSHs: []policyv1.SSH{},
|
||||
SSHs: []policyv2.SSH{},
|
||||
},
|
||||
len(MustTestVersions),
|
||||
)
|
||||
|
@ -252,23 +262,26 @@ func TestSSHIsBlockedInACL(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := sshScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:integration-test": {"user1@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:integration-test"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:80"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRange{First: 80, Last: 80}),
|
||||
},
|
||||
},
|
||||
},
|
||||
SSHs: []policyv1.SSH{
|
||||
SSHs: []policyv2.SSH{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:integration-test"},
|
||||
Destinations: []string{"user1@"},
|
||||
Users: []string{"ssh-it-user"},
|
||||
Sources: policyv2.SSHSrcAliases{groupp("group:integration-test")},
|
||||
Destinations: policyv2.SSHDstAliases{usernamep("user1@")},
|
||||
Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -301,30 +314,33 @@ func TestSSHUserOnlyIsolation(t *testing.T) {
|
|||
t.Parallel()
|
||||
|
||||
scenario := sshScenario(t,
|
||||
&policyv1.ACLPolicy{
|
||||
Groups: map[string][]string{
|
||||
"group:ssh1": {"user1@"},
|
||||
"group:ssh2": {"user2@"},
|
||||
&policyv2.Policy{
|
||||
Groups: policyv2.Groups{
|
||||
policyv2.Group("group:ssh1"): []policyv2.Username{policyv2.Username("user1@")},
|
||||
policyv2.Group("group:ssh2"): []policyv2.Username{policyv2.Username("user2@")},
|
||||
},
|
||||
ACLs: []policyv1.ACL{
|
||||
ACLs: []policyv2.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"*"},
|
||||
Destinations: []string{"*:*"},
|
||||
Action: "accept",
|
||||
Protocol: "tcp",
|
||||
Sources: []policyv2.Alias{wildcard()},
|
||||
Destinations: []policyv2.AliasWithPorts{
|
||||
aliasWithPorts(wildcard(), tailcfg.PortRangeAny),
|
||||
},
|
||||
},
|
||||
},
|
||||
SSHs: []policyv1.SSH{
|
||||
SSHs: []policyv2.SSH{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:ssh1"},
|
||||
Destinations: []string{"user1@"},
|
||||
Users: []string{"ssh-it-user"},
|
||||
Sources: policyv2.SSHSrcAliases{groupp("group:ssh1")},
|
||||
Destinations: policyv2.SSHDstAliases{usernamep("user1@")},
|
||||
Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")},
|
||||
},
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"group:ssh2"},
|
||||
Destinations: []string{"user2@"},
|
||||
Users: []string{"ssh-it-user"},
|
||||
Sources: policyv2.SSHSrcAliases{groupp("group:ssh2")},
|
||||
Destinations: policyv2.SSHDstAliases{usernamep("user2@")},
|
||||
Users: []policyv2.SSHUser{policyv2.SSHUser("ssh-it-user")},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -5,15 +5,19 @@ import (
|
|||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/netip"
|
||||
"strings"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/cenkalti/backoff/v4"
|
||||
policyv2 "github.com/juanfont/headscale/hscontrol/policy/v2"
|
||||
"github.com/juanfont/headscale/hscontrol/util"
|
||||
"github.com/juanfont/headscale/integration/tsic"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"tailscale.com/tailcfg"
|
||||
"tailscale.com/types/ptr"
|
||||
)
|
||||
|
||||
const (
|
||||
|
@ -419,10 +423,76 @@ func countMatchingLines(in io.Reader, predicate func(string) bool) (int, error)
|
|||
// return peer
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// Helper functions for creating typed policy entities
|
||||
|
||||
// wildcard returns a wildcard alias (*).
|
||||
func wildcard() policyv2.Alias {
|
||||
return policyv2.Wildcard
|
||||
}
|
||||
|
||||
// usernamep returns a pointer to a Username as an Alias.
|
||||
func usernamep(name string) policyv2.Alias {
|
||||
return ptr.To(policyv2.Username(name))
|
||||
}
|
||||
|
||||
// hostp returns a pointer to a Host.
|
||||
func hostp(name string) policyv2.Alias {
|
||||
return ptr.To(policyv2.Host(name))
|
||||
}
|
||||
|
||||
// groupp returns a pointer to a Group as an Alias.
|
||||
func groupp(name string) policyv2.Alias {
|
||||
return ptr.To(policyv2.Group(name))
|
||||
}
|
||||
|
||||
// tagp returns a pointer to a Tag as an Alias.
|
||||
func tagp(name string) policyv2.Alias {
|
||||
return ptr.To(policyv2.Tag(name))
|
||||
}
|
||||
|
||||
// prefixp returns a pointer to a Prefix from a CIDR string.
|
||||
func prefixp(cidr string) policyv2.Alias {
|
||||
prefix := netip.MustParsePrefix(cidr)
|
||||
return ptr.To(policyv2.Prefix(prefix))
|
||||
}
|
||||
|
||||
// aliasWithPorts creates an AliasWithPorts structure from an alias and ports.
|
||||
func aliasWithPorts(alias policyv2.Alias, ports ...tailcfg.PortRange) policyv2.AliasWithPorts {
|
||||
return policyv2.AliasWithPorts{
|
||||
Alias: alias,
|
||||
Ports: ports,
|
||||
}
|
||||
}
|
||||
|
||||
// usernameOwner returns a Username as an Owner for use in TagOwners.
|
||||
func usernameOwner(name string) policyv2.Owner {
|
||||
return ptr.To(policyv2.Username(name))
|
||||
}
|
||||
|
||||
// groupOwner returns a Group as an Owner for use in TagOwners.
|
||||
func groupOwner(name string) policyv2.Owner {
|
||||
return ptr.To(policyv2.Group(name))
|
||||
}
|
||||
|
||||
// usernameApprover returns a Username as an AutoApprover.
|
||||
func usernameApprover(name string) policyv2.AutoApprover {
|
||||
return ptr.To(policyv2.Username(name))
|
||||
}
|
||||
|
||||
// groupApprover returns a Group as an AutoApprover.
|
||||
func groupApprover(name string) policyv2.AutoApprover {
|
||||
return ptr.To(policyv2.Group(name))
|
||||
}
|
||||
|
||||
// tagApprover returns a Tag as an AutoApprover.
|
||||
func tagApprover(name string) policyv2.AutoApprover {
|
||||
return ptr.To(policyv2.Tag(name))
|
||||
}
|
||||
//
|
||||
// // findPeerByHostname takes a hostname and a map of peers from status.Peer, and returns a *ipnstate.PeerStatus
|
||||
// // if there is a peer with the given hostname. If no peer is found, nil is returned.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue