tailscale/control/policy/policy_test.go

157 lines
3.7 KiB
Go

// Copyright (c) 2020 Tailscale Inc & AUTHORS All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package policy
import (
"testing"
"github.com/google/go-cmp/cmp"
"tailscale.com/wgengine/filter"
)
type PortRange = filter.PortRange
type IPPortRange = filter.IPPortRange
var syntax_errors = []string{
`{ "ACLs": []! }`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "xPorts": ["100.122.98.50:22"]}
]}`,
`{ "ACLs": [
{"Action": "drop", "Users": [], "Ports": ["100.122.98.50:22"]}
]}`,
`{ "ACLs": [
{"Users": [], "Ports": ["100.122.98.50:22"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4:0"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["0.0.0.0:12"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["*:0"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4:5:6"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4.5:12"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4::12"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4:0-0"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4:1-10,2-"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4:1-10,*"]}
]}`,
`{ "ACLs": [
{"Action": "accept", "Users": [], "Ports": ["1.2.3.4,5.6.7.8:1-10"]}
]}`,
`{ "Hosts": {"mailserver": "not-an-ip"} }`,
`{ "Hosts": {"mailserver": "1.2.3.4:55"} }`,
`{ "xGroups": {
"bob": ["user1", "user2"]
}}`,
}
func TestSyntaxErrors(t *testing.T) {
for _, s := range syntax_errors {
_, err := Parse(s)
if err == nil {
t.Fatalf("Parse passed when it shouldn't. json:\n---\n%v\n---", s)
}
}
}
func ippr(ip IP, start, end uint16) []IPPortRange {
return []IPPortRange{
IPPortRange{ip, PortRange{start, end}},
}
}
func TestPolicy(t *testing.T) {
// Check ACL table parsing
usermap := map[string][]IP{
"A@b.com": []IP{0x08010101, 0x08020202},
"role:admin": []IP{0x02020202},
"user1@org": []IP{0x99010101, 0x99010102},
// user2 is intentionally missing
"user3@org": []IP{0x99030303},
"user4@org": []IP{},
}
want := filter.Matches{
{SrcIPs: []IP{0x08010101, 0x08020202}, DstPorts: []IPPortRange{
IPPortRange{0x01020304, PortRange{22, 22}},
IPPortRange{0x05060708, PortRange{23, 24}},
IPPortRange{0x05060708, PortRange{27, 28}},
}},
{SrcIPs: []IP{0x02020202}, DstPorts: ippr(0x08010101, 22, 22)},
{SrcIPs: []IP{0}, DstPorts: []IPPortRange{
IPPortRange{0x647a6232, PortRange{0, 65535}},
IPPortRange{0, PortRange{443, 443}},
}},
{SrcIPs: []IP{0x99010101, 0x99010102, 0x99030303}, DstPorts: ippr(0x01020304, 999, 999)},
}
p, err := Parse(`
{
// Test comment
"Hosts": {
"h1": "1.2.3.4", /* test comment */
"h2": "5.6.7.8"
},
"Groups": {
"group:eng": ["user1@org", "user2@org", "user3@org", "user4@org"]
},
"ACLs": [
{"Action": "accept", "Users": ["a@b.com"], "Ports": ["h1:22", "h2:23-24,27-28"]},
{"Action": "accept", "Users": ["role:Admin"], "Ports": ["8.1.1.1:22"]},
{"Action": "accept", "Users": ["*"], "Ports": ["100.122.98.50:*", "*:443"]},
{"Action": "accept", "Users": ["group:eng"], "Ports": ["h1:999"]},
]}
`)
if err != nil {
t.Fatalf("Parse failed: %v", err)
}
matches, err := p.Expand(usermap)
if err != nil {
t.Fatalf("Expand failed: %v", err)
}
if diff := cmp.Diff(want, matches); diff != "" {
t.Fatalf("Expand mismatch (-want +got):\n%s", diff)
}
}