only send relevant filterrules to nodes
Signed-off-by: Kristoffer Dalby <kristoffer@tailscale.com>
This commit is contained in:
parent
2675ff4b94
commit
88ca2501d1
4 changed files with 489 additions and 454 deletions
|
@ -125,122 +125,6 @@ func TestInvalidTagValidUser(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestPortGroup(t *testing.T) {
|
||||
machine := types.Machine{
|
||||
ID: 0,
|
||||
MachineKey: "foo",
|
||||
NodeKey: "bar",
|
||||
DiscoKey: "faa",
|
||||
Hostname: "testmachine",
|
||||
UserID: 0,
|
||||
User: types.User{
|
||||
Name: "testuser",
|
||||
},
|
||||
RegisterMethod: util.RegisterMethodAuthKey,
|
||||
IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.5")},
|
||||
}
|
||||
|
||||
acl := []byte(`
|
||||
{
|
||||
"groups": {
|
||||
"group:example": [
|
||||
"testuser",
|
||||
],
|
||||
},
|
||||
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"group:example",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := policy.LoadACLPolicyFromBytes(acl, "hujson")
|
||||
assert.NoError(t, err)
|
||||
|
||||
got, _, err := policy.GenerateFilterRules(pol, &machine, types.Machines{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
want := []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"100.64.0.5/32"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRange{Last: 65535}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("TestPortGroup() unexpected result (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPortUser(t *testing.T) {
|
||||
machine := types.Machine{
|
||||
ID: 0,
|
||||
MachineKey: "12345",
|
||||
NodeKey: "bar",
|
||||
DiscoKey: "faa",
|
||||
Hostname: "testmachine",
|
||||
UserID: 0,
|
||||
User: types.User{
|
||||
Name: "testuser",
|
||||
},
|
||||
RegisterMethod: util.RegisterMethodAuthKey,
|
||||
IPAddresses: types.MachineAddresses{netip.MustParseAddr("100.64.0.9")},
|
||||
}
|
||||
|
||||
acl := []byte(`
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"testuser",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := policy.LoadACLPolicyFromBytes(acl, "hujson")
|
||||
assert.NoError(t, err)
|
||||
|
||||
got, _, err := policy.GenerateFilterRules(pol, &machine, types.Machines{})
|
||||
assert.NoError(t, err)
|
||||
|
||||
want := []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"100.64.0.9/32"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRange{Last: 65535}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(want, got); diff != "" {
|
||||
t.Errorf("TestPortUser() unexpected result (-want +got):\n%s", diff)
|
||||
}
|
||||
}
|
||||
|
||||
// this test should validate that we can expand a group in a TagOWner section and
|
||||
// match properly the IP's of the related hosts. The owner is valid and the tag is also valid.
|
||||
// the tag is matched in the Destinations section.
|
||||
|
|
|
@ -403,8 +403,8 @@ func Test_fullMapResponse(t *testing.T) {
|
|||
ACLs: []policy.ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"mini"},
|
||||
Destinations: []string{"100.64.0.2:*"},
|
||||
Sources: []string{"100.64.0.2"},
|
||||
Destinations: []string{"mini:*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -430,8 +430,9 @@ func Test_fullMapResponse(t *testing.T) {
|
|||
CollectServices: "false",
|
||||
PacketFilter: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"100.64.0.1/32", "100.64.0.2/32"},
|
||||
SrcIPs: []string{"100.64.0.2/32"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.64.0.1/32", Ports: tailcfg.PortRangeAny},
|
||||
{IP: "100.64.0.2/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -177,7 +177,7 @@ func (pol *ACLPolicy) generateFilterRules(
|
|||
srcIPs = append(srcIPs, srcs...)
|
||||
}
|
||||
|
||||
protocols, needsWildcard, err := parseProtocol(acl.Protocol)
|
||||
protocols, isWildcard, err := parseProtocol(acl.Protocol)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Msgf("Error parsing ACL %d. protocol unknown %s", index, acl.Protocol)
|
||||
|
@ -185,25 +185,52 @@ func (pol *ACLPolicy) generateFilterRules(
|
|||
return nil, err
|
||||
}
|
||||
|
||||
destPorts := []tailcfg.NetPortRange{}
|
||||
for destIndex, dest := range acl.Destinations {
|
||||
dests, err := pol.getNetPortRangeFromDestination(
|
||||
dest,
|
||||
machines,
|
||||
needsWildcard,
|
||||
)
|
||||
if err != nil {
|
||||
log.Error().
|
||||
Interface("dest", dest).
|
||||
Int("ACL index", index).
|
||||
Int("dest index", destIndex).
|
||||
Msgf("Error parsing ACL")
|
||||
// record if the rule is actually relevant for the given machine.
|
||||
isRelevant := false
|
||||
|
||||
destPorts := []tailcfg.NetPortRange{}
|
||||
for _, dest := range acl.Destinations {
|
||||
alias, port, err := parseDestination(dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expanded, err := pol.ExpandAlias(
|
||||
machines,
|
||||
alias,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if machine.IPAddresses.InIPSet(expanded) {
|
||||
isRelevant = true
|
||||
}
|
||||
|
||||
ports, err := expandPorts(port, isWildcard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dests := []tailcfg.NetPortRange{}
|
||||
for _, dest := range expanded.Prefixes() {
|
||||
for _, port := range *ports {
|
||||
pr := tailcfg.NetPortRange{
|
||||
IP: dest.String(),
|
||||
Ports: port,
|
||||
}
|
||||
dests = append(dests, pr)
|
||||
}
|
||||
}
|
||||
destPorts = append(destPorts, dests...)
|
||||
}
|
||||
|
||||
// if the rule does not apply to the machine we are evaluating,
|
||||
// do not add it to the list and continue.
|
||||
if !isRelevant {
|
||||
continue
|
||||
}
|
||||
|
||||
rules = append(rules, tailcfg.FilterRule{
|
||||
SrcIPs: srcIPs,
|
||||
DstPorts: destPorts,
|
||||
|
@ -368,44 +395,6 @@ func (pol *ACLPolicy) getIPsFromSource(
|
|||
return prefixes, nil
|
||||
}
|
||||
|
||||
// getNetPortRangeFromDestination returns a set of tailcfg.NetPortRange
|
||||
// which are associated with the dest alias.
|
||||
func (pol *ACLPolicy) getNetPortRangeFromDestination(
|
||||
dest string,
|
||||
machines types.Machines,
|
||||
needsWildcard bool,
|
||||
) ([]tailcfg.NetPortRange, error) {
|
||||
alias, port, err := parseDestination(dest)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
expanded, err := pol.ExpandAlias(
|
||||
machines,
|
||||
alias,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ports, err := expandPorts(port, needsWildcard)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
dests := []tailcfg.NetPortRange{}
|
||||
for _, dest := range expanded.Prefixes() {
|
||||
for _, port := range *ports {
|
||||
pr := tailcfg.NetPortRange{
|
||||
IP: dest.String(),
|
||||
Ports: port,
|
||||
}
|
||||
dests = append(dests, pr)
|
||||
}
|
||||
}
|
||||
|
||||
return dests, nil
|
||||
}
|
||||
|
||||
func parseDestination(dest string) (string, string, error) {
|
||||
var tokens []string
|
||||
|
||||
|
@ -605,14 +594,14 @@ func excludeCorrectlyTaggedNodes(
|
|||
return out
|
||||
}
|
||||
|
||||
func expandPorts(portsStr string, needsWildcard bool) (*[]tailcfg.PortRange, error) {
|
||||
func expandPorts(portsStr string, isWild bool) (*[]tailcfg.PortRange, error) {
|
||||
if isWildcard(portsStr) {
|
||||
return &[]tailcfg.PortRange{
|
||||
{First: portRangeBegin, Last: portRangeEnd},
|
||||
}, nil
|
||||
}
|
||||
|
||||
if needsWildcard {
|
||||
if isWild {
|
||||
return nil, ErrWildcardIsNeeded
|
||||
}
|
||||
|
||||
|
|
|
@ -30,42 +30,388 @@ func (s *Suite) TestWrongPath(c *check.C) {
|
|||
c.Assert(err, check.NotNil)
|
||||
}
|
||||
|
||||
func (s *Suite) TestBrokenHuJson(c *check.C) {
|
||||
acl := []byte(`
|
||||
func TestParsing(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
format string
|
||||
acl string
|
||||
want []tailcfg.FilterRule
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "invalid-hujson",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
`)
|
||||
_, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.NotNil)
|
||||
}
|
||||
|
||||
func (s *Suite) TestInvalidPolicyHuson(c *check.C) {
|
||||
acl := []byte(`
|
||||
`,
|
||||
want: []tailcfg.FilterRule{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "valid-hujson-invalid-content",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"valid_json": true,
|
||||
"but_a_policy_though": false
|
||||
}
|
||||
`)
|
||||
_, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.NotNil)
|
||||
c.Assert(err, check.Equals, ErrEmptyPolicy)
|
||||
"valid_json": true,
|
||||
"but_a_policy_though": false
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "invalid-cidr",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{"example-host-1": "100.100.100.100/42"}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{},
|
||||
wantErr: true,
|
||||
},
|
||||
{
|
||||
name: "basic-rule",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
func (s *Suite) TestParseHosts(c *check.C) {
|
||||
var hosts Hosts
|
||||
err := hosts.UnmarshalJSON(
|
||||
[]byte(
|
||||
`{"example-host-1": "100.100.100.100","example-host-2": "100.100.101.100/24"}`,
|
||||
),
|
||||
)
|
||||
c.Assert(hosts, check.NotNil)
|
||||
c.Assert(err, check.IsNil)
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"subnet-1",
|
||||
"192.168.1.0/24"
|
||||
],
|
||||
"dst": [
|
||||
"*:22,3389",
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"100.100.101.0/24", "192.168.1.0/24"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "0.0.0.0/0", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
||||
{IP: "0.0.0.0/0", Ports: tailcfg.PortRange{First: 3389, Last: 3389}},
|
||||
{IP: "::/0", Ports: tailcfg.PortRange{First: 22, Last: 22}},
|
||||
{IP: "::/0", Ports: tailcfg.PortRange{First: 3389, Last: 3389}},
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "parse-protocol",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
func (s *Suite) TestParseInvalidCIDR(c *check.C) {
|
||||
var hosts Hosts
|
||||
err := hosts.UnmarshalJSON([]byte(`{"example-host-1": "100.100.100.100/42"}`))
|
||||
c.Assert(hosts, check.IsNil)
|
||||
c.Assert(err, check.NotNil)
|
||||
"acls": [
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "tcp",
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "udp",
|
||||
"dst": [
|
||||
"host-1:53",
|
||||
],
|
||||
},
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "icmp",
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
IPProto: []int{protocolTCP},
|
||||
},
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRange{First: 53, Last: 53}},
|
||||
},
|
||||
IPProto: []int{protocolUDP},
|
||||
},
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
IPProto: []int{protocolICMP, protocolIPv6ICMP},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "port-wildcard",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "port-range",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"subnet-1",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:5400-5500",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"100.100.101.0/24"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{
|
||||
IP: "100.100.100.100/32",
|
||||
Ports: tailcfg.PortRange{First: 5400, Last: 5500},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "port-group",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"groups": {
|
||||
"group:example": [
|
||||
"testuser",
|
||||
],
|
||||
},
|
||||
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"group:example",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"200.200.200.200/32"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "port-user",
|
||||
format: "hujson",
|
||||
acl: `
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"testuser",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"200.200.200.200/32"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "port-wildcard-yaml",
|
||||
format: "yaml",
|
||||
acl: `
|
||||
---
|
||||
hosts:
|
||||
host-1: 100.100.100.100/32
|
||||
subnet-1: 100.100.101.100/24
|
||||
acls:
|
||||
- action: accept
|
||||
src:
|
||||
- "*"
|
||||
dst:
|
||||
- host-1:*
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "ipv6-yaml",
|
||||
format: "yaml",
|
||||
acl: `
|
||||
---
|
||||
hosts:
|
||||
host-1: 100.100.100.100/32
|
||||
subnet-1: 100.100.101.100/24
|
||||
acls:
|
||||
- action: accept
|
||||
src:
|
||||
- "*"
|
||||
dst:
|
||||
- host-1:*
|
||||
`,
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{"0.0.0.0/0", "::/0"},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{IP: "100.100.100.100/32", Ports: tailcfg.PortRangeAny},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
pol, err := LoadACLPolicyFromBytes([]byte(tt.acl), tt.format)
|
||||
|
||||
if tt.wantErr && err == nil {
|
||||
t.Errorf("parsing() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
} else if !tt.wantErr && err != nil {
|
||||
t.Errorf("parsing() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{
|
||||
IPAddresses: types.MachineAddresses{
|
||||
netip.MustParseAddr("100.100.100.100"),
|
||||
},
|
||||
}, types.Machines{
|
||||
types.Machine{
|
||||
IPAddresses: types.MachineAddresses{
|
||||
netip.MustParseAddr("200.200.200.200"),
|
||||
},
|
||||
User: types.User{
|
||||
Name: "testuser",
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("parsing() error = %v, wantErr %v", err, tt.wantErr)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
if diff := cmp.Diff(tt.want, rules); diff != "" {
|
||||
t.Errorf("parsing() unexpected result (-want +got):\n%s", diff)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Suite) TestRuleInvalidGeneration(c *check.C) {
|
||||
|
@ -205,37 +551,6 @@ func (s *Suite) TestRuleInvalidGeneration(c *check.C) {
|
|||
c.Assert(rules, check.IsNil)
|
||||
}
|
||||
|
||||
func (s *Suite) TestBasicRule(c *check.C) {
|
||||
acl := []byte(`
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"subnet-1",
|
||||
"192.168.1.0/24"
|
||||
],
|
||||
"dst": [
|
||||
"*:22,3389",
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.IsNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
}
|
||||
|
||||
// TODO(kradalby): Make tests values safe, independent and descriptive.
|
||||
func (s *Suite) TestInvalidAction(c *check.C) {
|
||||
pol := &ACLPolicy{
|
||||
|
@ -286,199 +601,6 @@ func (s *Suite) TestInvalidTagOwners(c *check.C) {
|
|||
c.Assert(errors.Is(err, ErrInvalidTag), check.Equals, true)
|
||||
}
|
||||
|
||||
func (s *Suite) TestPortRange(c *check.C) {
|
||||
acl := []byte(`
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"action": "accept",
|
||||
"src": [
|
||||
"subnet-1",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:5400-5500",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(pol, check.NotNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
|
||||
c.Assert(rules, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts[0].Ports.First, check.Equals, uint16(5400))
|
||||
c.Assert(rules[0].DstPorts[0].Ports.Last, check.Equals, uint16(5500))
|
||||
}
|
||||
|
||||
func (s *Suite) TestProtocolParsing(c *check.C) {
|
||||
acl := []byte(`
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "tcp",
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "udp",
|
||||
"dst": [
|
||||
"host-1:53",
|
||||
],
|
||||
},
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"proto": "icmp",
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(pol, check.NotNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
|
||||
c.Assert(rules, check.HasLen, 3)
|
||||
c.Assert(rules[0].IPProto[0], check.Equals, protocolTCP)
|
||||
c.Assert(rules[1].IPProto[0], check.Equals, protocolUDP)
|
||||
c.Assert(rules[2].IPProto[1], check.Equals, protocolIPv6ICMP)
|
||||
}
|
||||
|
||||
func (s *Suite) TestPortWildcard(c *check.C) {
|
||||
acl := []byte(`
|
||||
{
|
||||
"hosts": {
|
||||
"host-1": "100.100.100.100",
|
||||
"subnet-1": "100.100.101.100/24",
|
||||
},
|
||||
|
||||
"acls": [
|
||||
{
|
||||
"Action": "accept",
|
||||
"src": [
|
||||
"*",
|
||||
],
|
||||
"dst": [
|
||||
"host-1:*",
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "hujson")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(pol, check.NotNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
|
||||
c.Assert(rules, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts[0].Ports.First, check.Equals, uint16(0))
|
||||
c.Assert(rules[0].DstPorts[0].Ports.Last, check.Equals, uint16(65535))
|
||||
c.Assert(rules[0].SrcIPs, check.HasLen, 2)
|
||||
c.Assert(rules[0].SrcIPs[0], check.Equals, "0.0.0.0/0")
|
||||
}
|
||||
|
||||
func (s *Suite) TestPortWildcardYAML(c *check.C) {
|
||||
acl := []byte(`---
|
||||
hosts:
|
||||
host-1: 100.100.100.100/32
|
||||
subnet-1: 100.100.101.100/24
|
||||
acls:
|
||||
- action: accept
|
||||
src:
|
||||
- "*"
|
||||
dst:
|
||||
- host-1:*`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "yaml")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(pol, check.NotNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
|
||||
c.Assert(rules, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts[0].Ports.First, check.Equals, uint16(0))
|
||||
c.Assert(rules[0].DstPorts[0].Ports.Last, check.Equals, uint16(65535))
|
||||
c.Assert(rules[0].SrcIPs, check.HasLen, 2)
|
||||
c.Assert(rules[0].SrcIPs[0], check.Equals, "0.0.0.0/0")
|
||||
}
|
||||
|
||||
func (s *Suite) TestBasicIpv6YAML(c *check.C) {
|
||||
acl := []byte(`
|
||||
---
|
||||
hosts:
|
||||
host-1: 100.100.100.100/32
|
||||
subnet-1: 100.100.101.100/24
|
||||
acls:
|
||||
- action: accept
|
||||
src:
|
||||
- "*"
|
||||
dst:
|
||||
- 0.0.0.0/0:*
|
||||
- ::/0:*
|
||||
- fd7a:115c:a1e0::2:22
|
||||
`)
|
||||
pol, err := LoadACLPolicyFromBytes(acl, "yaml")
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(pol, check.NotNil)
|
||||
|
||||
rules, err := pol.generateFilterRules(&types.Machine{}, types.Machines{})
|
||||
c.Assert(err, check.IsNil)
|
||||
c.Assert(rules, check.NotNil)
|
||||
|
||||
c.Assert(rules, check.HasLen, 1)
|
||||
c.Assert(rules[0].DstPorts, check.HasLen, 3)
|
||||
c.Assert(rules[0].DstPorts[0].IP, check.Equals, "0.0.0.0/0")
|
||||
c.Assert(rules[0].DstPorts[0].Ports.First, check.Equals, uint16(0))
|
||||
c.Assert(rules[0].DstPorts[0].Ports.Last, check.Equals, uint16(65535))
|
||||
c.Assert(rules[0].DstPorts[1].IP, check.Equals, "::/0")
|
||||
c.Assert(rules[0].DstPorts[1].Ports.First, check.Equals, uint16(0))
|
||||
c.Assert(rules[0].DstPorts[1].Ports.Last, check.Equals, uint16(65535))
|
||||
c.Assert(rules[0].DstPorts[2].IP, check.Equals, "fd7a:115c:a1e0::2/128")
|
||||
c.Assert(rules[0].DstPorts[2].Ports.First, check.Equals, uint16(22))
|
||||
c.Assert(rules[0].DstPorts[2].Ports.Last, check.Equals, uint16(22))
|
||||
c.Assert(rules[0].SrcIPs, check.HasLen, 2)
|
||||
c.Assert(rules[0].SrcIPs[0], check.Equals, "0.0.0.0/0")
|
||||
}
|
||||
|
||||
func Test_expandGroup(t *testing.T) {
|
||||
type field struct {
|
||||
pol ACLPolicy
|
||||
|
@ -1621,8 +1743,13 @@ func TestACLPolicy_generateFilterRules(t *testing.T) {
|
|||
},
|
||||
},
|
||||
args: args{
|
||||
machine: types.Machine{},
|
||||
peers: types.Machines{},
|
||||
machine: types.Machine{
|
||||
IPAddresses: types.MachineAddresses{
|
||||
netip.MustParseAddr("100.64.0.1"),
|
||||
netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"),
|
||||
},
|
||||
},
|
||||
peers: types.Machines{},
|
||||
},
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
|
@ -1648,7 +1775,64 @@ func TestACLPolicy_generateFilterRules(t *testing.T) {
|
|||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host1-can-reach-host2",
|
||||
name: "host1-can-reach-host2-no-rules",
|
||||
field: field{
|
||||
pol: ACLPolicy{
|
||||
ACLs: []ACL{
|
||||
{
|
||||
Action: "accept",
|
||||
Sources: []string{"100.64.0.2"},
|
||||
Destinations: []string{"100.64.0.1:*"},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
args: args{
|
||||
machine: types.Machine{
|
||||
IPAddresses: types.MachineAddresses{
|
||||
netip.MustParseAddr("100.64.0.1"),
|
||||
netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2221"),
|
||||
},
|
||||
User: types.User{Name: "mickael"},
|
||||
},
|
||||
peers: types.Machines{
|
||||
{
|
||||
IPAddresses: types.MachineAddresses{
|
||||
netip.MustParseAddr("100.64.0.2"),
|
||||
netip.MustParseAddr("fd7a:115c:a1e0:ab12:4843:2222:6273:2222"),
|
||||
},
|
||||
User: types.User{Name: "mickael"},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{
|
||||
"100.64.0.2/32",
|
||||
"fd7a:115c:a1e0:ab12:4843:2222:6273:2222/128",
|
||||
},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{
|
||||
IP: "100.64.0.1/32",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 0,
|
||||
Last: 65535,
|
||||
},
|
||||
},
|
||||
{
|
||||
IP: "fd7a:115c:a1e0:ab12:4843:2222:6273:2221/128",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 0,
|
||||
Last: 65535,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "host1-can-reach-host2-no-rules",
|
||||
field: field{
|
||||
pol: ACLPolicy{
|
||||
ACLs: []ACL{
|
||||
|
@ -1678,30 +1862,7 @@ func TestACLPolicy_generateFilterRules(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
want: []tailcfg.FilterRule{
|
||||
{
|
||||
SrcIPs: []string{
|
||||
"100.64.0.1/32",
|
||||
"fd7a:115c:a1e0:ab12:4843:2222:6273:2221/128",
|
||||
},
|
||||
DstPorts: []tailcfg.NetPortRange{
|
||||
{
|
||||
IP: "100.64.0.2/32",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 0,
|
||||
Last: 65535,
|
||||
},
|
||||
},
|
||||
{
|
||||
IP: "fd7a:115c:a1e0:ab12:4843:2222:6273:2222/128",
|
||||
Ports: tailcfg.PortRange{
|
||||
First: 0,
|
||||
Last: 65535,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
want: []tailcfg.FilterRule{},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue