diff --git a/hscontrol/policy/v2/tailscale_acl_compat_test.go b/hscontrol/policy/v2/tailscale_acl_compat_test.go deleted file mode 100644 index 580e1de4..00000000 --- a/hscontrol/policy/v2/tailscale_acl_compat_test.go +++ /dev/null @@ -1,9937 +0,0 @@ -// This file is "generated" by Claude. -// It contains a large set of input ACL/Policy JSON configurations that -// the AI agent has systematically applied to a Tailnet on Tailscale SaaS -// and then observed the individual clients connected to the Tailnet -// with a given policy and recorded the resulting Packet filter rules sent -// to the clients. -// -// There is likely a lot of duplicate or overlapping tests, however, the main -// exercise of this work was to create a comperehensive test set for comparing -// the behaviour of our policy engine and the upstream one. -// -// We aim to keep these tests to make sure we do not regress as we evolve -// and improve our policy implementation. -// This file is NOT intended for developer/humans to change and should be -// consider a "black box" test suite. - -package v2 - -import ( - "net/netip" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" - "github.com/juanfont/headscale/hscontrol/policy/policyutil" - "github.com/juanfont/headscale/hscontrol/types" - "github.com/stretchr/testify/require" - "gorm.io/gorm" - "tailscale.com/tailcfg" -) - -// ptrAddr is a helper to create a pointer to a netip.Addr. -func ptrAddr(s string) *netip.Addr { - addr := netip.MustParseAddr(s) - return &addr -} - -// setupTailscaleCompatUsers returns the test users for compatibility tests. -func setupTailscaleCompatUsers() types.Users { - return types.Users{ - {Model: gorm.Model{ID: 1}, Name: "kratail2tid"}, - } -} - -// setupTailscaleCompatNodes returns the test nodes for compatibility tests. -// The node configuration matches the Tailscale test environment: -// - 1 user-owned node (user1) -// - 4 tagged nodes (tagged-server, tagged-client, tagged-db, tagged-web). -func setupTailscaleCompatNodes(users types.Users) types.Nodes { - // Node: user1 - User-owned by kratail2tid - nodeUser1 := &types.Node{ - ID: 1, - GivenName: "user1", - User: &users[0], - UserID: &users[0].ID, - IPv4: ptrAddr("100.90.199.68"), - IPv6: ptrAddr("fd7a:115c:a1e0::2d01:c747"), - Hostinfo: &tailcfg.Hostinfo{}, - } - - // Node: tagged-server - Has tag:server - nodeTaggedServer := &types.Node{ - ID: 2, - GivenName: "tagged-server", - IPv4: ptrAddr("100.108.74.26"), - IPv6: ptrAddr("fd7a:115c:a1e0::b901:4a87"), - Tags: []string{"tag:server"}, - Hostinfo: &tailcfg.Hostinfo{}, - } - - // Node: tagged-client - Has tag:client - nodeTaggedClient := &types.Node{ - ID: 3, - GivenName: "tagged-client", - IPv4: ptrAddr("100.80.238.75"), - IPv6: ptrAddr("fd7a:115c:a1e0::7901:ee86"), - Tags: []string{"tag:client"}, - Hostinfo: &tailcfg.Hostinfo{}, - } - - // Node: tagged-db - Has tag:database - nodeTaggedDB := &types.Node{ - ID: 4, - GivenName: "tagged-db", - IPv4: ptrAddr("100.74.60.128"), - IPv6: ptrAddr("fd7a:115c:a1e0::2f01:3c9c"), - Tags: []string{"tag:database"}, - Hostinfo: &tailcfg.Hostinfo{}, - } - - // Node: tagged-web - Has tag:web - nodeTaggedWeb := &types.Node{ - ID: 5, - GivenName: "tagged-web", - IPv4: ptrAddr("100.94.92.91"), - IPv6: ptrAddr("fd7a:115c:a1e0::ef01:5c81"), - Tags: []string{"tag:web"}, - Hostinfo: &tailcfg.Hostinfo{}, - } - - return types.Nodes{ - nodeUser1, - nodeTaggedServer, - nodeTaggedClient, - nodeTaggedDB, - nodeTaggedWeb, - } -} - -// findNodeByGivenName finds a node by its GivenName field. -func findNodeByGivenName(nodes types.Nodes, name string) *types.Node { - for _, n := range nodes { - if n.GivenName == name { - return n - } - } - - return nil -} - -// tailscaleCompatTest defines a test case for Tailscale compatibility testing. -type tailscaleCompatTest struct { - name string // Test name - policy string // HuJSON policy as multiline raw string - wantFilters map[string][]tailcfg.FilterRule // node GivenName -> expected filters -} - -// basePolicyTemplate provides the standard groups, tagOwners, and hosts -// that are used in all Tailscale compatibility tests. -const basePolicyPrefix = `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [` - -const basePolicySuffix = ` - ] -}` - -// makePolicy creates a full policy from just the ACL rules portion. -func makePolicy(aclRules string) string { - return basePolicyPrefix + aclRules + basePolicySuffix -} - -// cmpOptions returns comparison options for FilterRule slices. -// It sorts SrcIPs and DstPorts to handle ordering differences. -func cmpOptions() []cmp.Option { - return []cmp.Option{ - cmpopts.SortSlices(func(a, b string) bool { return a < b }), - cmpopts.SortSlices(func(a, b tailcfg.NetPortRange) bool { - if a.IP != b.IP { - return a.IP < b.IP - } - - if a.Ports.First != b.Ports.First { - return a.Ports.First < b.Ports.First - } - - return a.Ports.Last < b.Ports.Last - }), - cmpopts.SortSlices(func(a, b int) bool { return a < b }), - } -} - -// Tailscale uses partitioned CGNAT CIDR ranges for wildcard source expansion -// (excluding the ChromeOS VM range 100.115.92.0/23). Headscale uses the simpler -// full CGNAT range (100.64.0.0/10) and Tailscale ULA range (fd7a:115c:a1e0::/48). -// This is functionally equivalent for access control purposes. -// -// For reference, Tailscale's partitioned ranges are: -// var tailscaleCGNATCIDRs = []string{ -// "100.64.0.0/11", -// "100.96.0.0/12", -// "100.112.0.0/15", -// "100.114.0.0/16", -// "100.115.0.0/18", -// "100.115.64.0/20", -// "100.115.80.0/21", -// "100.115.88.0/22", -// "100.115.94.0/23", -// "100.115.96.0/19", -// "100.115.128.0/17", -// "100.116.0.0/14", -// "100.120.0.0/13", -// "fd7a:115c:a1e0::/48", -// } - -// TestTailscaleCompatWildcardACLs tests wildcard ACL rules (* source and destination). -// These are the most fundamental tests for basic allow-all and IP-based rules. -func TestTailscaleCompatWildcardACLs(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "allow_all_wildcard", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["*:*"]} - `), - // All nodes receive the same filter for allow-all rule. - // NOTE: Tailscale expands `*` source to partitioned CGNAT CIDR ranges: - // 100.64.0.0/11, 100.96.0.0/12, 100.112.0.0/15, etc. plus fd7a:115c:a1e0::/48 - // Headscale uses the full 100.64.0.0/10 and fd7a:115c:a1e0::/48 ranges. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full range. - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "single_ip_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["100.90.199.68"], "dst": ["*:*"]} - `), - // Single IP source: Headscale resolves the IP to a node and includes ALL of the - // node's IPs (both IPv4 and IPv6). Tailscale uses only the literal IP specified. - // TODO: Tailscale only includes the literal IP "100.90.199.68/32" without IPv6. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // TODO: Tailscale only includes the literal IP: - // SrcIPs: []string{"100.90.199.68/32"}, - // Headscale: Resolves IP to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "cidr_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["100.64.0.0/16"], "dst": ["*:*"]} - `), - // CIDR source is passed through unchanged to the filter. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{"100.64.0.0/16"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{"100.64.0.0/16"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{"100.64.0.0/16"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{"100.64.0.0/16"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{"100.64.0.0/16"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "single_ip_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["100.108.74.26:*"]} - `), - // Single IP destination: ONLY that node receives the filter. - // KEY INSIGHT: Destination filters are only sent to nodes that ARE the destination. - // NOTE: This IP (100.108.74.26) is tagged-server. - // NOTE: Headscale resolves the IP to a node and includes ALL of the node's IPs. - // TODO: Tailscale only includes the literal destination IP without IPv6. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale only includes the literal destination IP: - // DstPorts: []tailcfg.NetPortRange{ - // {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - // }, - // Headscale: Resolves IP to node and includes ALL node IPs (IPv4+IPv6) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "cidr_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["100.64.0.0/12:*"]} - `), - // CIDR destination: only nodes with IPs in the CIDR range receive the filter. - // 100.64.0.0/12 covers 100.64.0.0 - 100.79.255.255 - // Of our test nodes, only tagged-db (100.74.60.128) falls in this range. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, // 100.90.199.68 is NOT in 100.64.0.0/12 - "tagged-server": nil, // 100.108.74.26 is NOT in 100.64.0.0/12 - "tagged-client": nil, // 100.80.238.75 is NOT in 100.64.0.0/12 - "tagged-db": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.64.0.0/12", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, // 100.94.92.91 is NOT in 100.64.0.0/12 - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatBasicTags tests basic tag-to-tag ACL rules. -// These tests verify that tags are correctly expanded to node IPs -// and that filters are distributed to the correct destination nodes. -func TestTailscaleCompatBasicTags(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "tag_client_to_tag_server_port_22", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "tag_as_source_wildcard_dest", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["*:*"]} - `), - // When dst is *, all nodes should receive the filter - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "multiple_source_tags", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "tag_as_destination_only", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["tag:server:22"]} - `), - // When using wildcard source and tag destination, ONLY the tagged node receives the filter. - // This is different from tag_as_source_wildcard_dest where all nodes receive the filter. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_destination_tags", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "tag:web:80"]} - `), - // Multiple destination tags in a single rule. - // Each tagged node receives ONLY its own destination portion. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "all_tagged_nodes_as_source_to_specific_destination", - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:database:5432"]} - `), - // All tagged nodes as source (including the destination node itself). - // Only the destination node receives the filter. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - // Handle nil vs empty slice comparison - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatUsersGroups tests user and group ACL rules. -func TestTailscaleCompatUsersGroups(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "user_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["kratail2tid@"], "dst": ["*:*"]} - `), - // User as source expands to IPs of nodes owned by that user - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "user_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["kratail2tid@:*"]} - `), - // User as destination - only user-owned nodes receive the filter - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["*:*"]} - `), - // Group as source expands to IPs of nodes owned by group members - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "group_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["group:admins:*"]} - `), - // Group as destination - only nodes owned by group members receive the filter - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_destinations_different_ports", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]} - `), - // Each destination node receives ONLY its own destination portion - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatAutogroups tests autogroup ACL rules. -func TestTailscaleCompatAutogroups(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "autogroup_member_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]} - `), - // autogroup:member expands to IPs of user-owned nodes only - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "autogroup_tagged_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]} - `), - // autogroup:tagged expands to IPs of all tagged nodes - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "autogroup_member_plus_tag_client", - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]} - `), - // Sources are merged into one Srcs array - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "autogroup_self_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]} - `), - // autogroup:self allows a node to access ITSELF. - // The source wildcard `*` is narrowed to the node's own IP for autogroup:self. - // KEY INSIGHT: Tagged nodes do NOT receive autogroup:self filters. - // Only user-owned nodes can use autogroup:self. - // NOTE: For autogroup:self destinations, both Tailscale and Headscale narrow - // the wildcard source to only the same-user untagged nodes. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // Source is narrowed to the node's own IPs for autogroup:self. - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // Tailscale uses CIDR format: "100.90.199.68/32" and "fd7a:115c:a1e0::2d01:c747/128" - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, // Tagged nodes do NOT receive autogroup:self filters - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "autogroup_internet_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:internet:*"]} - `), - // autogroup:internet produces NO PacketFilter entries. - // This autogroup relates to exit node routing, not direct node-to-node filters. - // It controls what traffic can be routed through exit nodes to the internet. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "autogroup_member_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:member:*"]} - `), - // autogroup:member as destination - only user-owned nodes receive the filter. - // Tagged nodes do NOT receive this filter. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "autogroup_self_mixed_with_tag", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]} - `), - // KEY FINDING: Mixed destinations create SEPARATE filter entries with different Srcs! - // - autogroup:self narrows Srcs to the user's own IPs - // - tag:server keeps Srcs as full wildcard - // user1 gets ONLY the self filter (narrowed Srcs to user1's IPs) - // tagged-server gets ONLY the tag filter (full wildcard Srcs) - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // autogroup:self narrows Srcs to user's own IPs - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - // tag:server keeps full wildcard Srcs - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, // Not in destination - "tagged-db": nil, // Not in destination - "tagged-web": nil, // Not in destination - }, - }, - { - name: "autogroup_tagged_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:tagged:*"]} - `), - // autogroup:tagged as destination - all tagged nodes receive the filter. - // User-owned nodes do NOT receive this filter. - // KEY INSIGHT: ReduceFilterRules filters DstPorts to only the current node's IPs. - // So each tagged node only sees its OWN IPs in DstPorts after reduction. - // TODO: Tailscale includes ALL tagged nodes' IPs in DstPorts for each node. - // Headscale only includes the current node's IPs after ReduceFilterRules. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale includes ALL tagged nodes' IPs: - // DstPorts: []tailcfg.NetPortRange{ - // {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - // {IP: "100.74.60.128/32", Ports: tailcfg.PortRangeAny}, - // {IP: "100.80.238.75/32", Ports: tailcfg.PortRangeAny}, - // {IP: "100.94.92.91/32", Ports: tailcfg.PortRangeAny}, - // {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRangeAny}, - // {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRangeAny}, - // {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny}, - // {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRangeAny}, - // }, - // Headscale: After ReduceFilterRules, only this node's IPs are in DstPorts - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment) - // Headscale: Only this node's IPs after ReduceFilterRules - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment) - // Headscale: Only this node's IPs after ReduceFilterRules - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale includes ALL tagged nodes' IPs (see tagged-server comment) - // Headscale: Only this node's IPs after ReduceFilterRules - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatHosts tests host alias ACL rules. -func TestTailscaleCompatHosts(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "host_as_destination", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["webserver:80"]} - `), - // Host reference webserver = 100.108.74.26 = tagged-server - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // TODO: Tailscale only includes the literal IPv4 for host aliases: - // DstPorts: []tailcfg.NetPortRange{ - // {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // }, - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "host_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["webserver"], "dst": ["*:*"]} - `), - // Host as source resolves to the defined IP - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // TODO: Tailscale only includes the literal IPv4 for host aliases: - // SrcIPs: []string{"100.108.74.26/32"}, - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - // TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment) - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - // TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment) - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - // TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment) - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - // TODO: Tailscale only includes the literal IPv4 for host aliases (see user1 comment) - // Headscale: Resolves host alias to node and includes ALL node IPs (IPv4+IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "cidr_host_as_source", - policy: makePolicy(` - {"action": "accept", "src": ["internal"], "dst": ["*:*"]} - `), - // CIDR host definition (10.0.0.0/8) is passed through unchanged - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatProtocolsPorts tests protocol and port ACL rules. -func TestTailscaleCompatProtocolsPorts(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "tcp_only_protocol", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "proto": "tcp", "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "udp_only_protocol", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "proto": "udp", "dst": ["tag:server:53"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 53, Last: 53}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 53, Last: 53}}, - }, - IPProto: []int{ProtocolUDP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "icmp_numeric_protocol", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "proto": "1", "dst": ["tag:server:*"]} - `), - // Numeric protocol values work (e.g., "1" for ICMP) - // Even for ICMP (which doesn't use ports), the ports field is 0-65535 - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "port_range", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["tag:server:80-443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_comma_separated_ports", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["tag:server:22,80,443"]} - `), - // Comma-separated ports expand into separate DstPorts entries - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_port", - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["tag:server:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRangeAny}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatMixedSources tests mixing different source types in a single rule. -// From findings/09-mixed-scenarios.md - Category 1: Mixed Sources (Single Rule). -func TestTailscaleCompatMixedSources(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "autogroup_tagged_plus_autogroup_member_full_tailnet", - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:22"]} - `), - // Full tailnet coverage: autogroup:tagged (all 4 tagged) + autogroup:member (user1) - // All 5 nodes' IPv4 and IPv6 addresses should be in Srcs (10 total entries) - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_plus_tag", - policy: makePolicy(` - {"action": "accept", "src": ["group:admins", "tag:client"], "dst": ["tag:server:22"]} - `), - // group:admins → user1's IPs + tag:client → tagged-client's IPs - // Both merged into single Srcs array (4 IPs total) - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "explicit_user_plus_tag", - policy: makePolicy(` - {"action": "accept", "src": ["kratail2tid@", "tag:client"], "dst": ["tag:server:22"]} - `), - // Explicit user kratail2tid@ → user1's IPs + tag:client → tagged-client's IPs - // Both merged into single Srcs array (4 IPs total) - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "cidr_plus_tag", - policy: makePolicy(` - {"action": "accept", "src": ["10.0.0.0/8", "tag:client"], "dst": ["tag:server:22"]} - `), - // CIDR 10.0.0.0/8 + tag:client IPs merged into single Srcs array - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "10.0.0.0/8", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "host_plus_tag", - policy: makePolicy(` - {"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]} - `), - // Host alias "internal" (10.0.0.0/8) + tag:client IPs merged into single Srcs array - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "10.0.0.0/8", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "webserver_host_plus_tag", - // Test 1.5: webserver (host) + tag:client - // Host aliases are IPv4 only; tags include IPv6. - policy: makePolicy(` - {"action": "accept", "src": ["webserver", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // TODO: Tailscale: webserver host = 100.108.74.26/32 (IPv4 only) - // Tailscale Srcs: ["100.108.74.26/32", "100.80.238.75/32", "fd7a:115c:a1e0::7901:ee86/128"] - // Headscale: Host resolves to node and includes ALL node IPs - SrcIPs: []string{ - "100.108.74.26/32", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "raw_ip_plus_tag", - // Test 1.6: 100.90.199.68 (raw IP) + tag:client - // Raw IPs are treated as literal CIDRs - policy: makePolicy(` - {"action": "accept", "src": ["100.90.199.68", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Raw IP 100.90.199.68 resolves to user1 node - Headscale includes all node IPs - // tag:client expands to tagged-client's IPs - // TODO: Tailscale may treat raw IP as literal /32 only without IPv6 - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", // user1 IPv6 added by Headscale - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_user_three_ways", - // Test 1.7: autogroup:member + group:admins + kratail2tid@ (same user 3 ways) - // All three resolve to user1, should deduplicate to just user1's IPs - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // All three sources resolve to user1 - should be deduplicated - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_ip_two_ways_as_source", - // Test 1.8: tag:server + webserver (same IP via tag and host) - // Both reference tagged-server's IP - should deduplicate - policy: makePolicy(` - {"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": { - { - // TODO: Tailscale: webserver host only adds IPv4 - // Tailscale Srcs: ["100.108.74.26/32", "fd7a:115c:a1e0::b901:4a87/128"] - // Headscale: Both tag:server and webserver resolve to all node IPs - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatComplexScenarios tests complex ACL rule combinations. -func TestTailscaleCompatComplexScenarios(t *testing.T) { - t.Parallel() - - users := setupTailscaleCompatUsers() - nodes := setupTailscaleCompatNodes(users) - - tests := []tailscaleCompatTest{ - { - name: "empty_group_produces_no_filter", - policy: makePolicy(` - {"action": "accept", "src": ["group:empty"], "dst": ["*:*"]} - `), - // Empty groups produce no filter entries - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_rules_same_source_merged", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80,443"]} - `), - // KEY INSIGHT: In Tailscale, multiple rules with the SAME source are MERGED into a - // single filter entry with all destination ports combined. - // Headscale now merges rules with identical SrcIPs and IPProto. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: Both ACL rules combined into single filter entry - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "different_sources_same_destination_separate", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:server:22"]} - `), - // KEY INSIGHT: Different sources are NEVER merged - always separate filter entries. - // Each source gets its own filter entry even with identical destinations. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "mixed_overlapping_rules", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:443"]} - `), - // In Tailscale: 4 rules → 2 filter entries (merged per-source) - // - tag:client rules merged (ports 22, 80) - // - tag:web rules merged (ports 22, 443) - // Headscale now merges rules with identical SrcIPs and IPProto. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: tag:client rules (ports 22, 80) - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Merged: tag:web rules (ports 22, 443) - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_tag_destinations_distributed", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]} - `), - // Multiple tag destinations are distributed to their respective nodes. - // tagged-server gets port 22, tagged-db gets port 5432. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - { - name: "same_node_different_ports_via_tag_and_host", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:80"]} - `), - // KEY FINDING: Same IP can appear multiple times in Dsts with different ports - // when referenced via different aliases (tag vs host). - // - tag:server adds both IPv4 and IPv6 (port 22) - // - webserver host adds only IPv4 (port 80) - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // TODO: Tailscale includes webserver:80 BEFORE tag:server:22 in Dsts: - // DstPorts: []tailcfg.NetPortRange{ - // {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // }, - // Headscale: tag destinations come first, then host destinations - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // Host alias "webserver" expands to node's IPs (IPv4 + IPv6) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_and_tag_destinations_distributed", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "tag:server:80"]} - `), - // Group:admins → user1, tag:server → tagged-server - // Each destination type distributed to its respective nodes. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_mixed_with_specific_source", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["*"], "dst": ["tag:server:80"]} - `), - // Wildcard `*` is NOT merged with specific sources. - // Each remains a separate filter entry. - // Wildcard expands to CIDR ranges, specific tag expands to node IP. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_src_different_dest_ports_merged", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]} - `), - // KEY FINDING: Same source, same dest node, different ports = MERGED - // 2 rules → 1 filter entry with all ports combined (4 Dsts: 2 ports × 2 IPs) - // Headscale now merges rules with identical SrcIPs and IPProto. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: Both rules combined - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_src_different_dest_nodes_separate", - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]} - `), - // Same source, different destination nodes = separate filter entries per node. - // Each destination node only receives its relevant filter. - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - // Category 2: Mixed Destinations - Additional tests - { - name: "tag_plus_raw_ip_same_node_different_ports", - // Test 2.3: tag:server:22 + 100.108.74.26:80 (tag + raw IP, same node) - // Same behavior as Test 2.2 - same IP can appear multiple times with different ports - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server adds both IPv4+IPv6 for port 22 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // Headscale resolves raw IP to node and includes all IPs (IPv4+IPv6) - // TODO: Tailscale adds only IPv4 for raw IP destinations - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "user_via_email_and_group_different_ports", - // Test 2.6: kratail2tid@:22 + group:admins:80 (same user via email + group) - // Same user referenced via email and group creates separate Dst entries per port - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["kratail2tid@:22", "group:admins:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Same user via email and group with different ports - 4 Dst entries total - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_host_destinations", - // Test 2.7: webserver:22 + database:5432 (multiple hosts) - // Host destinations are properly distributed to matching nodes - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["webserver:22", "database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Headscale resolves host alias to node and includes all IPs (IPv4+IPv6) - // TODO: Tailscale host alias is IPv4-only - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Headscale resolves host alias to node and includes all IPs (IPv4+IPv6) - // TODO: Tailscale host alias is IPv4-only - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - // Category 3: Overlapping References - Same entity via different names - { - name: "same_ip_via_tag_and_host_source", - // Test 3.1: src: [tag:server, webserver] - same IP via tag and host - // Duplicate IPs should be deduplicated in Srcs - policy: makePolicy(` - {"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:client:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": { - { - // tag:server gives IPv4+IPv6, webserver adds IPv4 again (but deduplicated) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_ip_port_via_tag_and_host_dest", - // Test 3.3: dst: [tag:server:22, webserver:22] - same IP:port via tag and host - // Destinations are NOT deduplicated - same IP:port can appear multiple times - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Destinations NOT deduplicated - same IP can appear twice - // tag:server adds IPv4:22 + IPv6:22 - // webserver adds IPv4:22 again + Headscale adds IPv6 too - // TODO: Tailscale: webserver adds IPv4:22 only (duplicated with tag:server) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_ip_port_via_tag_and_raw_ip_dest", - // Test 3.4: dst: [tag:server:22, 100.108.74.26:22] - tag + raw IP (identical) - // Same behavior as Test 3.3 - Dsts not deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Destinations NOT deduplicated - // tag:server adds IPv4:22 + IPv6:22 - // Raw IP adds IPv4:22 again + Headscale adds IPv6 too - // TODO: Tailscale: raw IP adds IPv4:22 only (duplicated) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "tag_database_plus_host_database_source", - // Test 3.5: src: [tag:database, database] - tag:database + host database (same node) - // Sources ARE deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["tag:database", "database"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Sources deduplicated: tag:database (IPv4+IPv6) + database host (IPv4) - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 4: Cross-Type Source→Destination Combinations - { - name: "autogroup_tagged_to_user", - // Test 4.2: autogroup:tagged → kratail2tid@:22 - // Tagged nodes → user-owned nodes - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["kratail2tid@:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // All 4 tagged nodes (8 IPs) can access user1:22 - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_to_host_alias", - // Test 4.3: group:admins → webserver:22 - // Group → host alias - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["webserver:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // Headscale resolves host alias to node and adds IPv6 too - // TODO: Tailscale host alias is IPv4-only - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 5: Order Effects - Order does NOT affect output - { - name: "source_order_independence", - // Test 5.1: Order of sources doesn't affect output - they are sorted - policy: makePolicy(` - {"action": "accept", "src": ["tag:web", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Sources are sorted: IPv4 first (ascending), then IPv6 (ascending) - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 6: Edge Cases - { - name: "cidr_host_as_source", - // Test 6.5: internal (10.0.0.0/8) → tag:server:22 - // CIDR host definitions work as sources - policy: makePolicy(` - {"action": "accept", "src": ["internal"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // CIDR host goes directly into SrcIPs - SrcIPs: []string{ - "10.0.0.0/8", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "cidr_host_as_destination_no_matching_nodes", - // Test 6.6: tag:client → internal:22 (CIDR host as destination) - // No nodes in 10.0.0.0/8 range, so no filters generated for any tailnet nodes - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["internal:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 7: Maximum Combinations - { - name: "multiple_tags_as_sources", - // Test 7.x: Multiple tags as sources - policy: makePolicy(` - {"action": "accept", "src": ["tag:client", "tag:web", "tag:database"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // All 3 tags' IPs - SrcIPs: []string{ - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "tag_to_multiple_destinations_ports", - // Test 7.x: tag:client → multiple destinations with different ports - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "tag:web:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 8: Redundancy Stress Tests - { - name: "user1_referenced_multiple_ways_as_source", - // Test 8.1: user1 referenced 5 ways - all deduplicated - // autogroup:member, kratail2tid@, group:admins, group:developers, 100.90.199.68 - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "kratail2tid@", "group:admins", "group:developers", "100.90.199.68"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // All 5 references resolve to user1 - deduplicated - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 9: All Tags + All Autogroups - { - name: "all_four_tags_as_sources", - // Test 9.1: All 4 tags as sources - policy: makePolicy(` - {"action": "accept", "src": ["tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["kratail2tid@:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // All 4 tagged nodes (8 IPs total) - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "all_four_tags_as_destinations", - // Test 9.2: All 4 tags as destinations - policy: makePolicy(` - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22", "tag:client:22", "tag:database:22", "tag:web:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "both_autogroups_as_sources", - // Test 9.3: autogroup:member + autogroup:tagged as sources (full tailnet) - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // All 5 nodes (10 IPs) - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 10: Multiple Rules with Mixed Types - { - name: "cross_type_separate_rules", - // Test 10.1: Different source types in separate rules - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - // Category 11: Port Variations with Mixed Types - { - name: "mixed_sources_with_port_range", - // Test 11.2: Mixed sources with port range - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:80-443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 14: Multi-Rule Compounding - { - name: "same_src_different_dests_two_rules", - // Test 14.1: Same src, different dests (2 rules) - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - { - name: "different_srcs_same_dest_two_rules", - // Test 14.6: Different srcs, same dest (2 rules) - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Two separate filter rules for each ACL rule - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 12: CIDR Host Combinations - { - name: "cidr_host_plus_tag_as_sources", - // Test 12.1: CIDR host + tag as sources - // internal (10.0.0.0/8) + tag:client - policy: makePolicy(` - {"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // CIDR host appears as-is in Srcs + tag:client IPs - SrcIPs: []string{ - "10.0.0.0/8", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "multiple_cidr_hosts_as_sources", - // Test 12.2: Multiple CIDR hosts as sources - // internal (10.0.0.0/8) + subnet24 (192.168.1.0/24) - policy: makePolicy(` - {"action": "accept", "src": ["internal", "subnet24"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Both CIDR hosts appear in Srcs - SrcIPs: []string{ - "10.0.0.0/8", - "192.168.1.0/24", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_cidr_via_host_and_raw", - // Test 12.4: Same CIDR referenced via host alias and raw CIDR - // internal (10.0.0.0/8) + 10.0.0.0/8 - should deduplicate - policy: makePolicy(` - {"action": "accept", "src": ["internal", "10.0.0.0/8"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Same CIDR referenced 2 ways should deduplicate - SrcIPs: []string{ - "10.0.0.0/8", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 13: autogroup:self Deep Dive - Tests where autogroup:self works - { - name: "wildcard_to_autogroup_self", - // Test 13.1: * → autogroup:self:* - // CRITICAL: autogroup:self NARROWS Srcs even when source is wildcard - // Only user-owned nodes receive filters; tagged nodes get empty - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // Srcs narrowed to user1's own IPs (NOT wildcard CIDRs) - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // Dsts = user1's own IPs with all ports (no CIDR notation for autogroup:self) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // Tagged nodes receive NO filters for autogroup:self - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_to_autogroup_self_specific_port", - // Test 13.2: * → autogroup:self:22 - // Specific port with autogroup:self - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "autogroup_member_to_self", - // Test 13.5: autogroup:member → autogroup:self:* - // autogroup:member is a valid source for autogroup:self - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "specific_user_to_self", - // Test 13.8: kratail2tid@ → autogroup:self:* - // Specific user email is a valid source for autogroup:self - policy: makePolicy(` - {"action": "accept", "src": ["kratail2tid@"], "dst": ["autogroup:self:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_to_self", - // Test 13.9: group:admins → autogroup:self:* - // Groups are valid sources for autogroup:self - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["autogroup:self:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_to_self_plus_tag", - // Test 13.16: * → [autogroup:self:*, tag:server:22] - // Mixed destinations with autogroup:self - different Srcs for each - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - // Self filter gets narrowed Srcs (user1's IPs only) - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // autogroup:self destinations use plain IPs (no CIDR notation) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - // Tag filter gets full wildcard Srcs - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - // Tag destinations use CIDR notation - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 14: More Multi-Rule Compounding - { - name: "same_src_same_dest_different_ports_two_rules", - // Test 14.2: Same src, same dest, different ports (2 rules) - // In Tailscale: MERGED into single filter entry with combined Dsts - // Headscale now merges rules with identical SrcIPs and IPProto. - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: Both rules combined - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "three_different_srcs_same_dest_different_ports", - // Test 14.21: 3 different sources → same dest, different ports - // Each rule becomes a separate filter entry - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "overlapping_dests_same_src_different_rules", - // Test 10.2: Overlapping destinations, different sources (2 rules) - // Each rule creates its own filter entry on destination nodes - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:*"]}, - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:server:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // Rule 1: group:admins → tag:server:* - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - // Rule 2: autogroup:tagged → tag:server:* - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "mixed_sources_comma_ports", - // Test 11.1: Mixed sources with comma-separated ports - // Each port becomes a separate Dst entry - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22,80,443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // Each port is a separate Dst entry (6 total: 3 ports × 2 IPs) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "full_autogroups_with_wildcard_and_specific_port", - // Test 11.4: Both autogroups with wildcard and specific port destinations - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:*", "tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - // All 5 nodes (10 IPs) as sources - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - // Wildcard port → 0-65535 - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - // Category 13: More autogroup:self tests - { - name: "wildcard_to_self_comma_ports", - // Test 13.3: * → autogroup:self:22,80,443 - // Comma-separated ports create separate Dsts entries - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:22,80,443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // 6 Dsts: 3 ports × 2 IPs (autogroup:self uses plain IPs) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_to_self_port_range", - // Test 13.4: * → autogroup:self:80-443 - // Port range preserved as First/Last - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:80-443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - // Port range preserved (autogroup:self uses plain IPs) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "self_twice_separate_rules_merged", - // Test 13.36: Self twice in separate rules (merged) - // * → autogroup:self:22 - // * → autogroup:self:80 - // Tailscale MERGES these into a single filter entry with 4 Dsts - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]}, - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Merged: Both rules combined into 1 filter entry with 4 Dsts - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Category 14: More Multi-Rule Compounding - { - name: "same_src_different_dests_two_rules_distributed", - // Test 14.1: Same src, different dests (2 rules) - // Rules distributed to different destination nodes - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": nil, - }, - }, - { - name: "different_srcs_same_dest_two_rules", - // Test 14.6: Different srcs, same dest (2 rules) - // Creates 2 SEPARATE filter entries (not merged) - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "group_and_user_same_person_same_dest", - // Test 14.8: Group + user (same person) → same dest (2 rules) - // Srcs DEDUPLICATED but Dsts NOT deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: 1 filter entry with Srcs deduplicated and 4 Dsts (duplicated) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "wildcard_to_self_plus_group", - // Test 13.20: * → [autogroup:self:*, group:admins:22] - // user1 gets TWO filter entries (different Srcs) - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "group:admins:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Entry 1: autogroup:self with narrowed Srcs - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: group:admins with full wildcard Srcs - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10 - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_src_same_dest_different_ports_two_rules_merged", - // Test 14.2: Same src, same dest, different ports (2 rules) - // MERGED into single filter entry with 4 Dsts - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: Both rules combined - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "three_different_srcs_same_dest_different_ports", - // Test 14.21: 3 different srcs → same dest, different ports (3 rules) - // Creates 3 SEPARATE filter entries - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "three_refs_same_user_same_dest_port", - // Test 14.22: 3 refs to same user → same dest:port (3 rules) - // Srcs DEDUPLICATED, Dsts NOT deduplicated (6 entries) - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - // Merged: 1 filter entry with Srcs deduplicated and 6 Dsts (not deduplicated) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_src_three_different_dests", - // Test 14.23: Same src → 3 different dests (3 rules) - // Each destination node receives its own filter entry - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:web:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "full_wildcard_plus_specific_rule", - // Test 14.36: Full wildcard + specific rule - // BOTH rules create filter entries (wildcard does NOT subsume specific) - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["*:*"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Wildcard rule only - { - // NOTE: Tailscale uses partitioned CGNAT CIDRs and IPProto [0] (any). - // Headscale uses full 100.64.0.0/10 and explicit IPProto list. - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - // TODO: Tailscale produces 2 entries: wildcard (IPProto [0]) + specific (IPProto [6,17,1,58]) - // Headscale produces 2 entries but with same IPProto - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "both_autogroups_to_wildcard", - // Test 14.42: Both autogroups → wildcard (full network) - // Different Srcs = separate entries, even with identical Dsts - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Entry 1: autogroup:tagged Srcs - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:member Srcs - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "triple_src_ref_each_rule", - // Test 14.45: Triple src ref each rule - // Sources deduplicated within each rule - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["group:admins:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Rule 2: tag:server + webserver + raw IP → group:admins (user1) - { - // Srcs deduplicated to 1 IP + IPv6 (all resolve to same tagged-server) - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - // Rule 1: autogroup:member + group:admins + user → tag:server - { - // Srcs deduplicated to user1's IPs (all 3 resolve to same user) - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "same_src_four_dests", - // Test 14.47: Same src → 4 dests - // Same Srcs across 4 rules = merged into single filter entry per destination node - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:database:5432"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:web:80"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["webserver:443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": nil, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "overlapping_destinations_different_sources", - // Test 10.2: Overlapping destinations, different sources - // Rules with same destination create SEPARATE filter entries, NOT merged - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["*:*"]}, - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Entry 1: group:admins → *:* - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:tagged → *:* - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_dest_node_via_tag_vs_host_source", - // Test 10.3: Same dest node via tag vs host source - // Same destination with different sources = separate entries - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["webserver"], "dst": ["tag:server:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Entry 1: tag:client → :22 - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: webserver → :80 (host source expands to node IPs) - { - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "three_rules_same_dest_different_sources", - // Test 10.4: 3 rules, same dest, different sources - // 3 separate filter entries on the same destination node - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Entry 1: * → :22 - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: tag:client → :80 - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 3: autogroup:member → :443 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "mixed_sources_in_multiple_rules", - // Test 10.5: Mixed sources in multiple rules - // Sources within a rule are deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["autogroup:member", "group:admins"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - // Rule 1: [tag:client, tag:web] → tag:server:22 - // Sources merged and deduplicated - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - // Rule 2: [autogroup:member, group:admins] → tag:database:5432 - // Both resolve to user1, deduplicated - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "mixed_sources_with_port_range_11_2", - // Test 11.2: Mixed sources with port range - // Port range preserved as First/Last - policy: makePolicy(` - {"action": "accept", "src": ["group:admins", "webserver"], "dst": ["tag:server:80-443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // group:admins (IPv4+IPv6) + webserver (node IPs) = 4 Srcs - SrcIPs: []string{ - "100.90.199.68/32", - "100.108.74.26/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_dest_node_different_ports_via_different_refs_2_2", - // Test 2.2: Same node referenced via tag and host with different ports - // Same IP can appear multiple times in Dsts with different ports - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server:22 adds IPv4 and IPv6 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // webserver:80 expands to node IPs (both IPv4 and IPv6) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_user_different_ports_via_email_and_group_2_6", - // Test 2.6: Same user referenced via email and group with different ports - // Destinations are NOT deduplicated when ports differ - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["kratail2tid@:22", "group:admins:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // 4 entries: user1's IPv4 and IPv6 for EACH port (22 and 80) - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "diff_srcs_same_dest_14_6", - // Test 14.6: Different srcs, same dest (2 rules) - // Different sources, same destination = 2 SEPARATE filter entries - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Entry 1: tag:client → :22 - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: tag:web → :22 - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "group_plus_user_same_person_same_dest_14_8", - // Test 14.8: Group + user (same person) → same dest (2 rules) - // Same person via group + user email = 1 filter entry, Srcs MERGED, Dsts NOT merged - policy: makePolicy(` - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Merged: 1 filter entry with 4 Dsts (duplicated) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "self_overlap_with_explicit_user_13_86", - // Test 13.86: self:22 + user:22 (overlap on same node) - // Different Srcs for self vs explicit user = separate entries - // NOTE: Tailscale produces 2 entries, one with wildcard CGNAT Srcs, one with user1's IPs. - // Headscale produces similar with full CGNAT range (100.64.0.0/10). - // In Headscale, autogroup:self entry comes FIRST, explicit user SECOND. - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:22", "kratail2tid@:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Entry 1: * → autogroup:self:22 (Srcs narrowed to user1's IPs, no CIDR in DstPorts) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: * → kratail2tid@:22 (wildcard Srcs, CIDR in DstPorts) - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "self_twice_different_ports_13_36", - // Test 13.36: Self twice in separate rules (merged) - // Multiple self rules with same source = MERGED into single filter entry - policy: makePolicy(` - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]}, - {"action": "accept", "src": ["*"], "dst": ["autogroup:self:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Merged: 1 filter entry with 4 Dsts - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - { - name: "six_rules_mixing_all_patterns", - // Test 14.50: 6 rules mixing all patterns - // Self-referential rules work, different Srcs create separate entries - policy: makePolicy(` - {"action": "accept", "src": ["tag:server"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:client:22"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:database:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:web:22"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["*:80"]}, - {"action": "accept", "src": ["*"], "dst": ["autogroup:member:443"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - // Entry 1: autogroup:member → *:80 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: * → autogroup:member:443 (user1 is in autogroup:member) - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - // Entry 1: tag:server → tag:server:22 (self-reference) - { - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:member → *:80 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - // Entry 1: tag:client → tag:client:22 (self-reference) - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:member → *:80 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - // Entry 1: tag:database → tag:database:22 (self-reference) - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:member → *:80 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - // Entry 1: tag:web → tag:web:22 (self-reference) - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: autogroup:member → *:80 - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 1: Mixed Sources - { - name: "autogroup_member_plus_tag_client_1_1", - // Test 1.1: autogroup:member + tag:client - // Sources are merged into single Srcs array - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // autogroup:member (user1) + tag:client = merged - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "group_admins_plus_tag_client_1_3", - // Test 1.3: group:admins + tag:client - // Sources are merged into single Srcs array - policy: makePolicy(` - {"action": "accept", "src": ["group:admins", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // group:admins (user1) + tag:client = merged - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "user_email_plus_tag_client_1_4", - // Test 1.4: kratail2tid@ + tag:client - // User email expanded to IPs + tag = merged - policy: makePolicy(` - {"action": "accept", "src": ["kratail2tid@", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "host_plus_tag_client_1_5", - // Test 1.5: webserver (host) + tag:client - // Host expands to node IPs + tag = merged - policy: makePolicy(` - {"action": "accept", "src": ["webserver", "tag:client"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-server": nil, - "tagged-web": nil, - "tagged-db": { - { - // webserver (tagged-server IPs) + tag:client = merged - SrcIPs: []string{ - "100.80.238.75/32", - "100.108.74.26/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "raw_ip_plus_tag_client_1_6", - // Test 1.6: 100.90.199.68 (raw IP) + tag:client - // Raw IP expands to node's both IPs + tag = merged - policy: makePolicy(` - {"action": "accept", "src": ["100.90.199.68", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Raw IP expands to user1's IPs + tag:client = merged (4 IPs) - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "user1_three_ways_1_7", - // Test 1.7: autogroup:member + group:admins + kratail2tid@ - // Same user referenced 3 ways = deduplicated to 2 IPs - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // All 3 references resolve to user1's IPs, deduplicated - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 2: Mixed Destinations - { - name: "tag_server_22_plus_tag_database_5432_2_1", - // Test 2.1: tag:server:22 + tag:database:5432 - // Multiple destinations in same rule, distributed to each node - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "tag_server_22_plus_raw_ip_80_2_3", - // Test 2.3: tag:server:22 + 100.108.74.26:80 (tag + raw IP, same node) - // Same node via tag and raw IP, different ports = NOT deduplicated in Dsts - // Raw IP destination expands to include node's IPv6 - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server:22 adds IPv4 and IPv6 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // raw IP:80 expands to both IPs - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "group_admins_22_plus_tag_server_80_2_4", - // Test 2.4: group:admins:22 + tag:server:80 - // User destination on port 22, tag destination on port 80 - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "tag:server:80"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "webserver_22_plus_database_5432_2_7", - // Test 2.7: webserver:22 + database:5432 (multiple hosts) - // Multiple host destinations - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["webserver:22", "database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // webserver host expands to tagged-server's IPs - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // database host expands to tagged-db's IPs - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 3: Overlapping References - { - name: "user1_three_ways_source_3_2", - // Test 3.2: user1 referenced 3 ways as source - // All resolve to same IPs, deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "kratail2tid@", "group:admins"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // All 3 references resolve to user1, deduplicated to 2 IPs - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_ip_port_tag_and_host_dest_3_3", - // Test 3.3: Same IP:port via tag and host as dest - // Same IP:port referenced two ways = NOT deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server:22 adds IPv4 and IPv6 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // webserver:22 also expands to same IPs - NOT deduplicated - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_ip_port_tag_and_raw_ip_dest_3_4", - // Test 3.4: Same IP:port via tag and raw IP - // Raw IP also expands to both IPs when matching a node - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "100.108.74.26:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server:22 adds IPv4 and IPv6 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // raw IP also expands to both IPs (NOT deduplicated) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 4: Cross-Type Source→Destination Combinations - { - name: "raw_ip_to_tag_server_4_7", - // Test 4.7: 100.90.199.68 → tag:server:22 - // Raw IP as source, tag as destination - // In Headscale, raw IP that matches a node expands to include IPv6 - policy: makePolicy(` - {"action": "accept", "src": ["100.90.199.68"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "tag_client_to_raw_ip_4_8", - // Test 4.8: tag:client → 100.108.74.26:22 - // Tag as source, raw IP as destination - // In Headscale, raw IP destination that matches a node expands to include IPv6 - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["100.108.74.26:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 7: Maximum Combinations ("Kitchen Sink") - { - name: "all_source_types_to_tag_server_7_1", - // Test 7.1: ALL source types → tag:server:22 - // Mix of all source types in one rule - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "autogroup:tagged", "group:admins", "tag:client", "webserver", "100.74.60.128"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // All sources merged: user1, all tagged, webserver, database IP - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 8: Redundancy Stress Tests - { - name: "user1_referenced_5_ways_8_1", - // Test 8.1: user1 referenced 5 ways - // All references deduplicated to user1's 2 IPs - policy: makePolicy(` - {"action": "accept", "src": ["autogroup:member", "group:admins", "group:developers", "kratail2tid@", "100.90.199.68"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // 5 references → deduplicated to user1's IPs + raw IP - // Note: raw IP only adds IPv4, others add both - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "tagged_server_3_ways_source_8_2", - // Test 8.2: tagged-server referenced 3 ways as source - // tag:server + webserver + raw IP = deduplicated - policy: makePolicy(` - {"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["tag:database:5432"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-server": nil, - "tagged-web": nil, - "tagged-db": { - { - // All 3 references resolve to tagged-server's IPs, deduplicated - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - { - name: "same_ip_port_3_ways_dest_8_5", - // Test 8.5: Same IP:port referenced 3 ways as destination - // tag:server:22 + webserver:22 + 100.108.74.26:22 - // Destinations are NOT deduplicated, raw IP also expands - policy: makePolicy(` - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "webserver:22", "100.108.74.26:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:server:22 adds both IPs - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // webserver:22 also adds both IPs (NOT deduplicated) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // raw IP also adds both IPs (NOT deduplicated) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Category 12: CIDR Host Combinations - { - name: "cidr_subnet_plus_tag_as_sources_12_3", - // Test 12.3: internal (CIDR host) + tag as sources - // External CIDR doesn't match nodes, tag does - policy: makePolicy(` - {"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]} - `), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // internal (10.0.0.0/8) + tag:client IPs - SrcIPs: []string{ - "10.0.0.0/8", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 5: Order Effects - // =========================================== - // Test 5.1a: Source Order - [tag:client, tag:web] - { - name: "source_order_client_web_5_1a", - // Test that order of sources doesn't affect output - policy: makePolicy(`{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Sources merged and sorted: IPv4 first (sorted), then IPv6 (sorted) - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 5.1b: Source Order Reversed - [tag:web, tag:client] - { - name: "source_order_web_client_5_1b", - // Same as 5.1a but reversed order - should produce identical output - policy: makePolicy(`{"action": "accept", "src": ["tag:web", "tag:client"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Should be identical to 5.1a - order doesn't matter - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 5.2a: Destination Order - [tag:server:22, tag:database:80] - { - name: "dest_order_server_db_5_2a", - // Test destination order - each node should get only its portion - policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:80"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 5.2b: Destination Order Reversed - [tag:database:80, tag:server:22] - { - name: "dest_order_db_server_5_2b", - // Same as 5.2a but reversed - should produce identical per-node filters - policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:database:80", "tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 5.3a: Mixed Source Types Order - [autogroup:member, tag:client] - { - name: "mixed_source_order_member_client_5_3a", - // Test mixed source types order - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Sources sorted: IPv4 first, then IPv6 - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 5.3b: Mixed Source Types Order Reversed - [tag:client, autogroup:member] - { - name: "mixed_source_order_client_member_5_3b", - // Same as 5.3a but reversed - should produce identical output - policy: makePolicy(`{"action": "accept", "src": ["tag:client", "autogroup:member"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Should be identical to 5.3a - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 6: Edge Cases - // =========================================== - // Test 6.3: Empty group as source - no filters expected - { - name: "empty_group_source_6_3", - // group:empty has no members, so no filters should be generated - policy: makePolicy(`{"action": "accept", "src": ["group:empty"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, // No filter because source group is empty - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Test 6.5: CIDR host (internal = 10.0.0.0/8) as source - { - name: "cidr_host_source_6_5", - // Host "internal" defined as 10.0.0.0/8 - CIDR goes directly into Srcs - policy: makePolicy(`{"action": "accept", "src": ["internal"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{"10.0.0.0/8"}, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 6.6: CIDR host as destination - no tailnet nodes match - { - name: "cidr_host_dest_6_6", - // internal (10.0.0.0/8) as destination - no tailnet nodes in this range - policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["internal:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // No nodes match 10.0.0.0/8, so no filters generated - }, - }, - - // =========================================== - // Category 9: All Tags + All Autogroups - // =========================================== - // Test 9.1: All 4 tags as sources - { - name: "all_four_tags_sources_9_1", - // All 4 tags combined as sources - policy: makePolicy(`{"action": "accept", "src": ["tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // 4 tags = 8 IPs (4 IPv4 + 4 IPv6, deduplicated) - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 9.2: All 4 tags as destinations - { - name: "all_four_tags_dests_9_2", - // All 4 tags as destinations - each node gets only its own IP:port - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22", "tag:client:22", "tag:database:22", "tag:web:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, // Not a destination - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 9.3: Both autogroups as sources - { - name: "both_autogroups_sources_9_3", - // autogroup:member + autogroup:tagged = full tailnet coverage - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Full tailnet: 5 nodes = 10 IPs (5 IPv4 + 5 IPv6) - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 10: Multiple Rules with Mixed Types - // =========================================== - // Test 10.1: Cross-type in separate rules - { - name: "cross_type_separate_rules_10_1", - // Rule 1: autogroup:member → tag:server:22 - // Rule 2: tag:client → group:admins:80 - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["group:admins:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 gets filter from Rule 2 (tag:client → group:admins:80) - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server gets filter from Rule 1 (autogroup:member → tag:server:22) - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 10.2: Overlapping destinations, different sources - { - name: "overlapping_dests_diff_sources_10_2", - // Rule 1: group:admins → tag:server:22 - // Rule 2: autogroup:tagged → tag:server:22 - // Same destination, different sources - creates separate filter entries - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server gets TWO separate filter entries (one per rule) - "tagged-server": { - // Rule 1: group:admins - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Rule 2: autogroup:tagged - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 10.3: Three rules to same destination - { - name: "three_rules_same_dest_10_3", - // Rule 1: autogroup:member → tag:server:22 - // Rule 2: tag:client → tag:server:22 - // Rule 3: group:admins → tag:server:22 - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server gets TWO filter entries (Rules 1+3 merged, Rule 2 separate) - "tagged-server": { - // Rules 1+3: autogroup:member and group:admins (same SrcIPs) merged - // DstPorts combined from both rules (duplicates included) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Rule 2: tag:client (different SrcIPs, not merged) - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 11: Port Variations with Mixed Types - // =========================================== - // Test 11.1: Mixed sources with comma ports - { - name: "mixed_sources_comma_ports_11_1", - // Comma-separated ports create separate Dsts entries - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["tag:server:22,80,443"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - }, - // 3 ports × 2 IPs = 6 Dsts entries - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 11.2: Mixed sources with port range - { - name: "mixed_sources_port_range_11_2", - // Port ranges preserved as First/Last in Dsts - policy: makePolicy(`{"action": "accept", "src": ["group:admins", "webserver"], "dst": ["tag:server:80-443"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // group:admins (IPv4+IPv6) + webserver (IPv4+IPv6 since it matches tagged-server node) - SrcIPs: []string{ - "100.108.74.26/32", - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 11.4: Full autogroups with wildcard port - { - name: "autogroups_wildcard_port_11_4", - // Wildcard port (*) expands to 0-65535 - policy: makePolicy(`{"action": "accept", "src": ["autogroup:tagged", "autogroup:member"], "dst": ["tag:server:*"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - // Full tailnet: 5 nodes = 10 IPs - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 13: autogroup:self Deep Dive - // =========================================== - // Test 13.1: Wildcard → self:* - { - name: "wildcard_to_self_all_ports_13_1", - // autogroup:self NARROWS Srcs even when source is wildcard - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - // Only user1 (user-owned) receives filter - "user1": { - { - // Srcs NARROWED to user1's IPs only (not wildcard CIDRs!) - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // Tagged nodes receive NO filters - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Test 13.2: Wildcard → self:22 - { - name: "wildcard_to_self_port_22_13_2", - // Specific port with self - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Test 13.5: autogroup:member → self:* - { - name: "member_to_self_13_5", - // autogroup:member works with autogroup:self - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:self:*"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Test 13.8: Specific user → self:* - { - name: "specific_user_to_self_13_8", - // Specific user email works with autogroup:self - policy: makePolicy(`{"action": "accept", "src": ["kratail2tid@"], "dst": ["autogroup:self:*"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - // Test 13.9: group:admins → self:* - { - name: "group_to_self_13_9", - // Groups work with autogroup:self - policy: makePolicy(`{"action": "accept", "src": ["group:admins"], "dst": ["autogroup:self:*"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - }, - }, - - // =========================================== - // Category 14: Multi-Rule Compounding - // =========================================== - // Test 14.1: Same src, different dests (2 rules) - { - name: "same_src_diff_dests_14_1", - // Same source, different destinations = separate filter entries per dest node - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.2: Same src, same dest, different ports (2 rules) - { - name: "same_src_same_dest_diff_ports_merged_14_2", - // Same source + dest node + different ports - // MERGED into 1 filter entry with 4 Dsts - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Merged: 1 entry with 4 DstPorts - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.6: Different srcs, same dest (2 rules) - { - name: "diff_srcs_same_dest_14_6", - // Different sources, same dest = 2 SEPARATE filter entries - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // TWO separate filter entries - "tagged-server": { - // Entry 1: tag:client - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - // Entry 2: tag:web - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.8: Group + user (same person) → same dest (2 rules) - { - name: "group_user_same_person_same_dest_14_8", - // Group + user (same person) - // MERGED into 1 filter entry (Srcs deduplicated, Dsts NOT) - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Merged: 1 entry with deduplicated Srcs but duplicated Dsts - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 7: Kitchen Sink Tests - // =========================================== - // Test 7.2: tag:client → ALL destination types - { - name: "all_dest_types_7_2", - // Test ALL destination types from one source - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:database:5432", "webserver:80", "database:443", "group:admins:8080", "kratail2tid@:3000", "100.108.74.26:9000"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-web": nil, - // user1 gets entries for user:3000 and group:8080 - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 3000, Last: 3000}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 3000, Last: 3000}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server gets tag:server:22, webserver:80, raw IP:9000 - // Note: Host aliases that match node IPs get expanded to include IPv6 - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db gets tag:database:5432 and database:443 - // Note: Host aliases that match node IPs get expanded to include IPv6 - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 7.3: 10 different sources → *:* - { - name: "ten_sources_to_wildcard_7_3", - // 10 different source types all deduplicated - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["autogroup:member", "autogroup:tagged", "group:admins", "group:developers", "kratail2tid@", "tag:client", "tag:web", "tag:database", "webserver", "database"], "dst": ["*:*"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // All nodes receive the deduplicated sources (including tagged-client since it's in *:*) - // The sources are: autogroup:member, autogroup:tagged, group:admins, group:developers, - // kratail2tid@, tag:client, tag:web, tag:database, webserver, database - // autogroup:tagged includes ALL tagged nodes: tagged-server, tagged-client, tagged-db, tagged-web - // All 5 nodes' IPs are included in the sources - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // =========================================== - // Category 12: CIDR Host Combinations - // =========================================== - // Test 12.1: CIDR host + tag as sources - { - name: "cidr_host_plus_tag_sources_12_1", - // CIDR host (10.0.0.0/8) combined with tag as sources - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["internal", "tag:client"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "10.0.0.0/8", - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 12.2: Multiple CIDR hosts as sources - { - name: "multiple_cidr_hosts_sources_12_2", - // Multiple CIDR hosts (10.0.0.0/8 + 192.168.1.0/24) - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["internal", "subnet24"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - { - SrcIPs: []string{ - "10.0.0.0/8", - "192.168.1.0/24", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 12.4: Host CIDR + raw CIDR (same value) as sources - { - name: "host_cidr_plus_raw_cidr_same_12_4", - // Same CIDR via host alias and raw value - should deduplicate - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["internal", "10.0.0.0/8"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // Deduplicated - only one 10.0.0.0/8 entry - "tagged-server": { - { - SrcIPs: []string{ - "10.0.0.0/8", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // =========================================== - // Additional Missing Tests from 09-mixed-scenarios.md - // =========================================== - // Test 6.2: * → [webserver:22, database:5432] - // Wildcard source + multiple host destinations - { - name: "wildcard_to_multiple_hosts_6_2", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["webserver:22", "database:5432"]}`), - // Wildcard `*` expands to all nodes (Headscale uses 0.0.0.0/0 and ::/0) - // Host destinations are properly distributed to matching nodes - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - // tagged-server gets webserver:22 (since webserver = 100.108.74.26 = tagged-server) - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - // NOTE: Tailscale uses partitioned CGNAT CIDRs, Headscale uses full 100.64.0.0/10: - // "100.115.94.0/23", "100.115.96.0/19", ..., "fd7a:115c:a1e0::/48" - // TODO: Host destination is IPv4-only in Tailscale, but Headscale - // resolves host aliases to node IPs and includes both IPv4+IPv6 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db gets database:5432 (since database = 100.74.60.128 = tagged-db) - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - // TODO: Host destination is IPv4-only in Tailscale - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 7.4: * → 9 destinations (multiple per node) - // Destinations: tag:server:22, tag:server:80, tag:server:443, tag:database:5432, - // tag:database:3306, tag:web:80, tag:web:443, webserver:8080, database:8080 - { - name: "wildcard_to_9_destinations_7_4", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:server:80", "tag:server:443", "tag:database:5432", "tag:database:3306", "tag:web:80", "tag:web:443", "webserver:8080", "database:8080"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - // tagged-server gets: tag:server:22/80/443 + webserver:8080 - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - // webserver:8080 (host alias - Headscale includes IPv4+IPv6) - // TODO: Tailscale host destinations are IPv4-only - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - // tag:server:22 (IPv4) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // tag:server:80 (IPv4) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:server:443 (IPv4) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - // tag:server:22 (IPv6) - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // tag:server:80 (IPv6) - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:server:443 (IPv6) - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db gets: tag:database:5432/3306 + database:8080 - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - // database:8080 (host alias - Headscale includes IPv4+IPv6) - // TODO: Tailscale host destinations are IPv4-only - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - // tag:database:5432 (IPv4) - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - // tag:database:3306 (IPv4) - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 3306, Last: 3306}}, - // tag:database:5432 (IPv6) - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - // tag:database:3306 (IPv6) - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 3306, Last: 3306}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web gets: tag:web:80/443 - "tagged-web": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - // tag:web:80 (IPv4) - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:web:443 (IPv4) - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - // tag:web:80 (IPv6) - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:web:443 (IPv6) - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 7.5: MANY sources → MANY destinations - // Sources: autogroup:member, group:admins, kratail2tid@, tag:client, tag:web, 100.80.238.75, 100.94.92.91 - // Destinations: tag:server:22, webserver:80, 100.108.74.26:443, group:admins:8080, kratail2tid@:9000 - { - name: "many_sources_many_destinations_7_5", - policy: makePolicy(`{"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@", "tag:client", "tag:web", "100.80.238.75", "100.94.92.91"], "dst": ["tag:server:22", "webserver:80", "100.108.74.26:443", "group:admins:8080", "kratail2tid@:9000"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 gets: group:admins:8080 + kratail2tid@:9000 - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // kratail2tid@:9000 - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - // group:admins:8080 - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server gets: tag:server:22 + webserver:80 + 100.108.74.26:443 - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // webserver:80 (host alias matches tagged-server, includes IPv6) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:server:22 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // 100.108.74.26:443 (raw IP matches node, so Headscale includes IPv6) - // TODO: Tailscale raw IP destinations are IPv4-only - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 8.3: tagged-db referenced 3 ways as source - // Sources: tag:database, database (host alias), 100.74.60.128 (raw IP) - // All 3 resolve to tagged-db - should be deduplicated in Srcs - { - name: "tagged_db_3_ways_source_8_3", - policy: makePolicy(`{"action": "accept", "src": ["tag:database", "database", "100.74.60.128"], "dst": ["tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server receives filter - // Srcs should be deduplicated: tag adds IPv6, host/raw IP are IPv4-only - "tagged-server": { - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 8.4: autogroup:tagged + all 4 tags as sources - // Sources: autogroup:tagged, tag:server, tag:client, tag:database, tag:web - // autogroup:tagged covers all 4 tags, so individual tags are redundant - // Should deduplicate to just 8 IPs (4 nodes × 2 IPs each) - { - name: "autogroup_tagged_plus_all_4_tags_8_4", - policy: makePolicy(`{"action": "accept", "src": ["autogroup:tagged", "tag:server", "tag:client", "tag:database", "tag:web"], "dst": ["autogroup:member:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 (autogroup:member) receives the filter - // Srcs = all 4 tagged nodes deduplicated = 8 IPs - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // =========================================== - // Additional Missing Tests - Batch 2 - // =========================================== - // Test 1.8: tag:server + webserver (same IP two ways as sources) - { - name: "tag_server_plus_webserver_same_ip_1_8", - policy: makePolicy(`{"action": "accept", "src": ["tag:server", "webserver"], "dst": ["tag:client:22"]}`), - // tag:server and webserver both resolve to tagged-server (100.108.74.26) - // Sources should be deduplicated - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-server": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-client receives the filter - "tagged-client": { - { - SrcIPs: []string{ - // Deduplicated: tag:server adds IPv4+IPv6, webserver adds IPv4 only - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 4.3: group:admins → webserver:22 - { - name: "group_admins_to_webserver_4_3", - policy: makePolicy(`{"action": "accept", "src": ["group:admins"], "dst": ["webserver:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server (webserver) receives the filter - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // TODO: Tailscale only includes IPv4 for host alias - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 4.4: webserver → group:admins:22 - { - name: "webserver_to_group_admins_4_4", - policy: makePolicy(`{"action": "accept", "src": ["webserver"], "dst": ["group:admins:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 (group:admins member) receives the filter - "user1": { - { - SrcIPs: []string{ - // TODO: Tailscale only includes IPv4 for host source - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 8.6: user1:22 referenced 4 ways as destination - // Destinations: group:admins:22, group:developers:22, kratail2tid@:22, 100.90.199.68:22 - { - name: "user1_4_ways_dest_8_6", - policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22", "group:developers:22", "kratail2tid@:22", "100.90.199.68:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 receives the filter - Dsts NOT deduplicated - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // kratail2tid@:22 - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // group:admins:22 - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // group:developers:22 - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // 100.90.199.68:22 (raw IP matches node, includes IPv6) - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 8.7: Same node, 5 ports via different references - // Destinations: tag:server:22, tag:server:80, tag:server:443, webserver:8080, 100.108.74.26:9000 - { - name: "same_node_5_ports_different_refs_8_7", - policy: makePolicy(`{"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22", "tag:server:80", "tag:server:443", "webserver:8080", "100.108.74.26:9000"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server receives the filter - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // webserver:8080 (host alias - includes IPv6) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 8080, Last: 8080}}, - // 100.108.74.26:9000 (raw IP - includes IPv6) - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 9000, Last: 9000}}, - // tag:server:22 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // tag:server:80 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - // tag:server:443 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 9.4: Wildcard to autogroup:self - { - name: "wildcard_to_autogroup_self_9_4", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*"]}`), - // Only user1 (user-owned) receives filter; tagged nodes don't support autogroup:self - // Sources narrowed to user1's own IPs (not full wildcard) - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // Note: autogroup:self destinations use raw IP format (no /32 suffix) - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 10.4: 3 rules, same dest, different sources - // Rule 1: * → tag:server:22 - // Rule 2: tag:client → tag:server:80 - // Rule 3: autogroup:member → tag:server:443 - { - name: "three_rules_same_dest_different_sources_10_4", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server receives 3 filter entries - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 10.5: Mixed sources in multiple rules - // Rule 1: [tag:client, tag:web] → tag:server:22 - // Rule 2: [autogroup:member, group:admins] → tag:database:5432 - { - name: "mixed_sources_multiple_rules_10_5", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"], - "group:developers": ["kratail2tid@"], - "group:empty": [] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26", - "database": "100.74.60.128", - "internal": "10.0.0.0/8", - "subnet24": "192.168.1.0/24" - }, - "acls": [ - {"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["autogroup:member", "group:admins"], "dst": ["tag:database:5432"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - // tagged-server receives filter from rule 1 - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db receives filter from rule 2 - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 11.3: Mixed sources with mixed port formats - // Destinations: tag:server:22, tag:server:80-443, tag:database:5432,3306 - { - name: "mixed_sources_mixed_port_formats_11_3", - policy: makePolicy(`{"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["tag:server:22", "tag:server:80-443", "tag:database:5432,3306"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-web": nil, - // tagged-server receives :22 and :80-443 - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // :22 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - // :80-443 - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db receives :5432,3306 - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // :5432 - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - // :3306 - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 3306, Last: 3306}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 3306, Last: 3306}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 12.5: Multiple CIDR + tag destinations - // Destinations: internal:22, subnet24:80, tag:server:443 - // CIDR destinations don't match tailnet nodes - { - name: "multiple_cidr_plus_tag_destinations_12_5", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["internal:22", "subnet24:80", "tag:server:443"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // Only tag:server:443 is delivered (CIDRs don't match tailnet nodes) - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 13.4: Wildcard → self:80-443 (port range) - { - name: "wildcard_to_self_port_range_13_4", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:80-443"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // Note: autogroup:self destinations use raw IP format (no /32 suffix) - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 13.16: Wildcard → self + tag:server:22 (mixed destinations) - { - name: "wildcard_to_self_plus_tag_server_13_16", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "tag:server:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1: receives narrowed Srcs for autogroup:self - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // Note: autogroup:self destinations use raw IP format (no /32 suffix) - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server: receives full wildcard Srcs for tag:server:22 - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 13.20: Wildcard → self + group:admins:22 (same dest node) - { - name: "wildcard_to_self_plus_group_admins_13_20", - policy: makePolicy(`{"action": "accept", "src": ["*"], "dst": ["autogroup:self:*", "group:admins:22"]}`), - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // user1 gets 2 filter entries: - // Entry 1: autogroup:self:* with narrowed Srcs (processed first due to autogroup:self splitting) - // Entry 2: group:admins:22 with full wildcard - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - // Note: autogroup:self destinations use raw IP format (no /32 suffix) - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 0, Last: 65535}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - - // ===== Category 14: Multi-Rule Tests ===== - - // Test 14.21: 3 different srcs → same dest, different ports (3 rules) - { - name: "three_diff_srcs_same_dest_diff_ports_14_21", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:server:80"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:server:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server: receives 3 separate filter entries (different Srcs = separate) - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.22: 3 refs to same user → same dest:port (3 rules) - // MERGED into 1 entry with 6 Dsts (not deduplicated) - { - name: "three_refs_same_user_same_dest_14_22", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["group:admins"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["kratail2tid@"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "tagged-server": { - // Merged: 1 entry with 6 Dsts (not deduplicated) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.23: Same src → 3 different dests (3 rules) - { - name: "same_src_three_diff_dests_14_23", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:5432"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:web:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - // Each destination node receives its own filter (same Srcs per node) - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.26: Same entity as both src and dst in 2 rules - // MERGED into 1 entry with 4 Dsts (not deduplicated) - { - name: "same_entity_src_and_dst_14_26", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:member"], "dst": ["autogroup:member:22"]}, - {"action": "accept", "src": ["group:admins"], "dst": ["group:admins:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - // Merged: 1 entry with 4 Dsts (not deduplicated) - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.27: User→user:22, group→user:80 (same Srcs, different ports) - // MERGED into 1 entry with 4 Dsts - { - name: "user_to_user_22_group_to_user_80_14_27", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["kratail2tid@"], "dst": ["kratail2tid@:22"]}, - {"action": "accept", "src": ["group:admins"], "dst": ["kratail2tid@:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - // Merged: 1 entry with 4 Dsts - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.29: tagged→tagged:22, specific tags→tagged:80 - { - name: "tagged_to_tagged_specific_tags_14_29", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:tagged:22"]}, - {"action": "accept", "src": ["tag:client", "tag:web"], "dst": ["autogroup:tagged:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - // Each tagged node receives 2 filter entries (different Srcs = separate) - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.42: Both autogroups → wildcard (full network) - { - name: "both_autogroups_to_wildcard_14_42", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["*:*"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["*:*"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // All nodes receive 2 filter entries (different Srcs = separate entries) - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.45: Triple src ref each rule - { - name: "triple_src_ref_each_rule_14_45", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:member", "group:admins", "kratail2tid@"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:server", "webserver", "100.108.74.26"], "dst": ["group:admins:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - // tagged-server: receives filter from rule 1 (triple user ref deduplicated to 1 IP) - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // user1: receives filter from rule 2 (triple ref deduplicated to tag:server IP) - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.47: Same src → 4 dests (4 rules) - { - name: "same_src_four_dests_14_47", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:database:5432"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:web:80"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["webserver:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - // tagged-server: merged entry for :22 and :443 (same SrcIPs) - "tagged-server": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.50: 6 rules mixing all patterns - { - name: "six_rules_mixed_patterns_14_50", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:server"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:client:22"]}, - {"action": "accept", "src": ["tag:database"], "dst": ["tag:database:22"]}, - {"action": "accept", "src": ["tag:web"], "dst": ["tag:web:22"]}, - {"action": "accept", "src": ["autogroup:member"], "dst": ["*:80"]}, - {"action": "accept", "src": ["*"], "dst": ["autogroup:member:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // user1: receives 2 entries: member→*:80 and *→user1:443 - "user1": { - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server: receives self-ref + member→*:80 - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "fd7a:115c:a1e0::b901:4a87/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-client: receives self-ref + member→*:80 - "tagged-client": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db: receives self-ref + member→*:80 - "tagged-db": { - { - SrcIPs: []string{ - "100.74.60.128/32", - "fd7a:115c:a1e0::2f01:3c9c/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web: receives self-ref + member→*:80 - "tagged-web": { - { - SrcIPs: []string{ - "100.94.92.91/32", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.90.199.68/32", - "fd7a:115c:a1e0::2d01:c747/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.17: Wildcard → group and user (same person):22 - // Test 14.17: * → group:admins:22 and * → kratail2tid@:22 - // MERGED into 1 entry with 4 Dsts (duplicated) - { - name: "wildcard_to_group_and_user_same_14_17", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["group:admins:22"]}, - {"action": "accept", "src": ["*"], "dst": ["kratail2tid@:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - // Merged: 1 entry with 4 Dsts (duplicated) - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.18: Tag → member and group (same):22 - // MERGED into 1 entry with 4 Dsts (duplicated) - { - name: "tag_to_member_and_group_same_14_18", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["autogroup:member:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["group:admins:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-server": nil, - "tagged-client": nil, - "tagged-db": nil, - "tagged-web": nil, - "user1": { - // Merged: 1 entry with 4 Dsts (duplicated) - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.20: Two rules with multi-dest, partial dest overlap - { - name: "two_rules_multi_dest_partial_overlap_14_20", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:database:5432"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80", "tag:web:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - // tagged-server: receives both wildcard:22 and tag:client:80 - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db: receives wildcard:5432 - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web: receives tag:client:443 - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.30: All→all subset, wildcard→wildcard - { - name: "all_to_all_subset_wildcard_wildcard_14_30", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["autogroup:member:22", "autogroup:tagged:80"]}, - {"action": "accept", "src": ["*"], "dst": ["*:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // user1: receives member:22 (first rule dst) + *:443 (second rule) - "user1": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.90.199.68/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2d01:c747/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web: receives tagged:80 (first rule dst) + *:443 (second rule) - "tagged-web": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // Other tagged nodes: same pattern - tagged:80 + *:443 - "tagged-server": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-client": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.80.238.75/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::7901:ee86/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.108.74.26/32", - "100.74.60.128/32", - "100.80.238.75/32", - "100.90.199.68/32", - "100.94.92.91/32", - "fd7a:115c:a1e0::2d01:c747/128", - "fd7a:115c:a1e0::2f01:3c9c/128", - "fd7a:115c:a1e0::7901:ee86/128", - "fd7a:115c:a1e0::b901:4a87/128", - "fd7a:115c:a1e0::ef01:5c81/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.37: Multiple wildcard src rules - // Rules with same SrcIPs going to the same node are MERGED - { - name: "multiple_wildcard_src_rules_14_37", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["*"], "dst": ["tag:database:5432"]}, - {"action": "accept", "src": ["*"], "dst": ["*:80"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "tagged-client": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server: receives rule 1 (:22) and rule 3 (:80) - MERGED - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db: receives rule 2 (:5432) and rule 3 (:80) - MERGED - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "user1": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.38: Wildcard dest + specific dest - // TODO: Tailscale subsumes specific into wildcard (1 entry), Headscale creates 2 separate entries - { - name: "wildcard_dest_plus_specific_dest_14_38", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["*:*"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // tagged-client: receives only wildcard (tag:server:22 doesn't apply to tagged-client) - "tagged-client": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server: receives both wildcard and specific (specific is subset) - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRangeAny}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.40: Wildcard in different positions - { - name: "wildcard_in_different_positions_14_40", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["tag:server:22", "tag:database:5432"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:80", "*:443"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - // user1: receives only *:443 from rule 2 - "user1": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-server: receives wildcard:22 and tag:client:80 and tag:client:443 - "tagged-server": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 80, Last: 80}}, - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db: receives wildcard:5432 and tag:client:443 - "tagged-db": { - { - SrcIPs: []string{ - "100.64.0.0/10", - "fd7a:115c:a1e0::/48", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 5432, Last: 5432}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web: receives only tag:client:443 - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-client: receives only tag:client:443 - "tagged-client": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "*", Ports: tailcfg.PortRange{First: 443, Last: 443}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - // Test 14.49: Same src → 5 dests (some overlap) - // TODO: Tailscale merges, Headscale creates separate entries but may deduplicate destinations - { - name: "same_src_five_dests_overlap_14_49", - policy: `{ - "groups": {"group:admins": ["kratail2tid@"]}, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"], - "tag:database": ["kratail2tid@"], - "tag:web": ["kratail2tid@"] - }, - "hosts": {"webserver": "100.108.74.26", "database": "100.74.60.128"}, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["tag:server:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:database:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["tag:web:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["webserver:22"]}, - {"action": "accept", "src": ["tag:client"], "dst": ["database:22"]} - ] - }`, - wantFilters: map[string][]tailcfg.FilterRule{ - "user1": nil, - "tagged-client": nil, - // tagged-server: receives rules 1 and 4 (tag:server:22 and webserver:22 resolve to same node) - // Note: Host alias (webserver) also resolves to both IPv4 and IPv6 when it matches a node - "tagged-server": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.108.74.26/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::b901:4a87/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-db: receives rules 2 and 5 (tag:database:22 and database:22 resolve to same node) - "tagged-db": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "100.74.60.128/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::2f01:3c9c/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - // tagged-web: receives rule 3 only - "tagged-web": { - { - SrcIPs: []string{ - "100.80.238.75/32", - "fd7a:115c:a1e0::7901:ee86/128", - }, - DstPorts: []tailcfg.NetPortRange{ - {IP: "100.94.92.91/32", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - {IP: "fd7a:115c:a1e0::ef01:5c81/128", Ports: tailcfg.PortRange{First: 22, Last: 22}}, - }, - IPProto: []int{ProtocolTCP, ProtocolUDP, ProtocolICMP, ProtocolIPv6ICMP}, - }, - }, - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - require.NoError(t, err, "failed to parse policy") - - err = pol.validate() - require.NoError(t, err, "policy validation failed") - - for nodeName, wantFilters := range tt.wantFilters { - node := findNodeByGivenName(nodes, nodeName) - require.NotNil(t, node, "node %s not found", nodeName) - - // Get compiled filters for this specific node - compiledFilters, err := pol.compileFilterRulesForNode(users, node.View(), nodes.ViewSlice()) - require.NoError(t, err, "failed to compile filters for node %s", nodeName) - - // Reduce to only rules where this node is a destination - gotFilters := policyutil.ReduceFilterRules(node.View(), compiledFilters) - - if len(wantFilters) == 0 && len(gotFilters) == 0 { - continue - } - - if diff := cmp.Diff(wantFilters, gotFilters, cmpOptions()...); diff != "" { - t.Errorf("node %s filters mismatch (-want +got):\n%s", nodeName, diff) - } - } - }) - } -} - -// TestTailscaleCompatErrorCases tests ACL configurations that should produce validation errors. -// These tests verify that Headscale correctly rejects invalid policies, matching Tailscale's behavior -// where the coordination server rejects the policy at update time (400 Bad Request). -// -// Reference: /home/kradalby/acl-explore/findings/09-mixed-scenarios.md. -func TestTailscaleCompatErrorCases(t *testing.T) { - t.Parallel() - - tests := []struct { - name string - policy string - wantErr string - reference string // Test case reference from findings - }{ - // Test 6.4: tag:nonexistent → tag:server:22 (ERROR) - // Tailscale error: "src=tag not found: \"tag:nonexistent\" (400)" - { - name: "undefined_tag_source_6_4", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["tag:nonexistent"], "dst": ["tag:server:22"]} - ] - }`, - wantErr: `tag not defined in policy: "tag:nonexistent"`, - reference: "Test 6.4: tag:nonexistent → tag:server:22", - }, - - // Test 13.41: autogroup:self as SOURCE (ERROR) - // Tailscale error: "\"autogroup:self\" not valid on the src side of a rule (400)" - { - name: "self_as_source_13_41", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["autogroup:self"], "dst": ["tag:server:22"]} - ] - }`, - wantErr: `autogroup:self can only be used in ACL destinations`, - reference: "Test 13.41: autogroup:self as SOURCE", - }, - - // Test 13.43: autogroup:self without port (ERROR) - // Tailscale error: "dst=\"autogroup:self\": port range \"self\": invalid first integer (400)" - { - name: "self_without_port_13_43", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["*"], "dst": ["autogroup:self"]} - ] - }`, - wantErr: `invalid port number`, - reference: "Test 13.43: autogroup:self without port", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - pol, err := unmarshalPolicy([]byte(tt.policy)) - // Check for parsing errors (some errors occur at parse time) - if err != nil { - require.ErrorContains(t, err, tt.wantErr, - "test %s (%s): expected parse error containing %q, got %q", - tt.name, tt.reference, tt.wantErr, err.Error()) - - return - } - - // Check for validation errors - err = pol.validate() - require.Error(t, err, "test %s (%s): expected validation error, got none", tt.name, tt.reference) - require.ErrorContains(t, err, tt.wantErr, - "test %s (%s): expected error containing %q, got %q", - tt.name, tt.reference, tt.wantErr, err.Error()) - }) - } -} - -// TestTailscaleCompatErrorCasesHeadscaleDiffers validates that Headscale correctly rejects -// policies that Tailscale also rejects. These tests verify that autogroup:self destination -// validation for ACL rules matches Tailscale's behavior. -// -// Tailscale validates that autogroup:self can only be used when ALL sources are -// users, groups, or autogroup:member. Headscale now performs this same validation. -// -// Reference: /home/kradalby/acl-explore/findings/09-mixed-scenarios.md. -func TestTailscaleCompatErrorCasesHeadscaleDiffers(t *testing.T) { - t.Parallel() - - // These tests verify that Headscale rejects policies the same way Tailscale does. - // Tailscale rejects these policies at validation time (400 Bad Request), - // and Headscale now does the same. - tests := []struct { - name string - policy string - tailscaleError string // What Tailscale returns (and Headscale should match) - reference string - }{ - // Test 2.5: tag:client → autogroup:self:* + tag:server:22 - // Tailscale REJECTS this - autogroup:self requires user/group sources - { - name: "tag_source_with_self_dest_2_5", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"], - "tag:client": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*", "tag:server:22"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 2.5: tag:client → autogroup:self:* + tag:server:22", - }, - - // Test 4.5: tag:client → autogroup:self:* - // Tailscale REJECTS this - autogroup:self requires user/group sources - { - name: "tag_source_to_self_dest_only_4_5", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:client": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 4.5: tag:client → autogroup:self:*", - }, - - // Test 6.1: autogroup:tagged → autogroup:self:* - // Tailscale REJECTS this - autogroup:tagged is NOT a valid source for autogroup:self - { - name: "autogroup_tagged_to_self_6_1", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 6.1: autogroup:tagged → autogroup:self:*", - }, - - // Test 9.5: [autogroup:member, autogroup:tagged] → [autogroup:self:*, tag:server:22] - // Tailscale REJECTS this - ANY invalid source (autogroup:tagged) invalidates the rule - { - name: "both_autogroups_to_self_plus_tag_9_5", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["autogroup:member", "autogroup:tagged"], "dst": ["autogroup:self:*", "tag:server:22"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 9.5: [autogroup:member, autogroup:tagged] → [autogroup:self:*, tag:server:22]", - }, - - // Test 13.6: autogroup:tagged → self:* - // Tailscale REJECTS this - same as 6.1 - { - name: "autogroup_tagged_to_self_13_6", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["autogroup:tagged"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 13.6: autogroup:tagged → self:*", - }, - - // Test 13.10: tag:client → self:* - // Tailscale REJECTS this - tags are not valid sources for autogroup:self - { - name: "tag_to_self_13_10", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:client": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["tag:client"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 13.10: tag:client → self:*", - }, - - // Test 13.13: Host → self:* - // Tailscale REJECTS this - hosts are not valid sources for autogroup:self - { - name: "host_to_self_13_13", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "hosts": { - "webserver": "100.108.74.26" - }, - "acls": [ - {"action": "accept", "src": ["webserver"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 13.13: Host → self:*", - }, - - // Test 13.14: Raw IP → self:* - // Tailscale REJECTS this - raw IPs are not valid sources for autogroup:self - { - name: "raw_ip_to_self_13_14", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:server": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["100.90.199.68"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 13.14: Raw IP (user1) → self:*", - }, - - // Test 13.25: [autogroup:member, tag:client] → self:* - // Tailscale REJECTS this - ANY invalid source (tag:client) invalidates the rule - { - name: "mixed_valid_invalid_sources_to_self_13_25", - policy: `{ - "groups": { - "group:admins": ["kratail2tid@"] - }, - "tagOwners": { - "tag:client": ["kratail2tid@"] - }, - "acls": [ - {"action": "accept", "src": ["autogroup:member", "tag:client"], "dst": ["autogroup:self:*"]} - ] - }`, - tailscaleError: "autogroup:self can only be used with users, groups, or supported autogroups (400)", - reference: "Test 13.25: [autogroup:member, tag:client] → self:*", - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - t.Parallel() - - // unmarshalPolicy calls validate() internally, so we expect it to fail - // with our validation error - _, err := unmarshalPolicy([]byte(tt.policy)) - require.Error(t, err, - "test %s (%s): should reject policy like Tailscale", - tt.name, tt.reference) - require.ErrorIs(t, err, ErrACLAutogroupSelfInvalidSource, - "test %s (%s): expected autogroup:self validation error", - tt.name, tt.reference) - }) - } -} diff --git a/hscontrol/policy/v2/tailscale_acl_data_compat_test.go b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go new file mode 100644 index 00000000..833e3233 --- /dev/null +++ b/hscontrol/policy/v2/tailscale_acl_data_compat_test.go @@ -0,0 +1,425 @@ +// This file implements a data-driven test runner for ACL compatibility tests. +// It loads JSON golden files from testdata/acl_results/ACL-*.json and compares +// headscale's ACL engine output against the expected packet filter rules. +// +// The JSON files were converted from the original inline Go struct test cases +// in tailscale_acl_compat_test.go. Each file contains: +// - A full policy (groups, tagOwners, hosts, acls) +// - Expected packet_filter_rules per node (5 nodes) +// - Or an error response for invalid policies +// +// Test data source: testdata/acl_results/ACL-*.json +// Original source: Tailscale SaaS API captures + headscale-generated expansions + +package v2 + +import ( + "encoding/json" + "net/netip" + "os" + "path/filepath" + "strings" + "testing" + + "github.com/google/go-cmp/cmp" + "github.com/google/go-cmp/cmp/cmpopts" + "github.com/juanfont/headscale/hscontrol/policy/policyutil" + "github.com/juanfont/headscale/hscontrol/types" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "gorm.io/gorm" + "tailscale.com/tailcfg" +) + +// ptrAddr is a helper to create a pointer to a netip.Addr. +func ptrAddr(s string) *netip.Addr { + addr := netip.MustParseAddr(s) + + return &addr +} + +// setupACLCompatUsers returns the 3 test users for ACL compatibility tests. +// Email addresses use @example.com domain, matching the converted Tailscale +// policy format (Tailscale uses @passkey and @dalby.cc). +func setupACLCompatUsers() types.Users { + return types.Users{ + {Model: gorm.Model{ID: 1}, Name: "kratail2tid", Email: "kratail2tid@example.com"}, + {Model: gorm.Model{ID: 2}, Name: "kristoffer", Email: "kristoffer@example.com"}, + {Model: gorm.Model{ID: 3}, Name: "monitorpasskeykradalby", Email: "monitorpasskeykradalby@example.com"}, + } +} + +// setupACLCompatNodes returns the 8 test nodes for ACL compatibility tests. +// Uses the same topology as the grants compat tests. +func setupACLCompatNodes(users types.Users) types.Nodes { + return types.Nodes{ + { + ID: 1, GivenName: "user1", + User: &users[0], UserID: &users[0].ID, + IPv4: ptrAddr("100.90.199.68"), IPv6: ptrAddr("fd7a:115c:a1e0::2d01:c747"), + Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 2, GivenName: "user-kris", + User: &users[1], UserID: &users[1].ID, + IPv4: ptrAddr("100.110.121.96"), IPv6: ptrAddr("fd7a:115c:a1e0::1737:7960"), + Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 3, GivenName: "user-mon", + User: &users[2], UserID: &users[2].ID, + IPv4: ptrAddr("100.103.90.82"), IPv6: ptrAddr("fd7a:115c:a1e0::9e37:5a52"), + Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 4, GivenName: "tagged-server", + IPv4: ptrAddr("100.108.74.26"), IPv6: ptrAddr("fd7a:115c:a1e0::b901:4a87"), + Tags: []string{"tag:server"}, Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 5, GivenName: "tagged-prod", + IPv4: ptrAddr("100.103.8.15"), IPv6: ptrAddr("fd7a:115c:a1e0::5b37:80f"), + Tags: []string{"tag:prod"}, Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 6, GivenName: "tagged-client", + IPv4: ptrAddr("100.83.200.69"), IPv6: ptrAddr("fd7a:115c:a1e0::c537:c845"), + Tags: []string{"tag:client"}, Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 7, GivenName: "subnet-router", + IPv4: ptrAddr("100.92.142.61"), IPv6: ptrAddr("fd7a:115c:a1e0::3e37:8e3d"), + Tags: []string{"tag:router"}, Hostinfo: &tailcfg.Hostinfo{}, + }, + { + ID: 8, GivenName: "exit-node", + IPv4: ptrAddr("100.85.66.106"), IPv6: ptrAddr("fd7a:115c:a1e0::7c37:426a"), + Tags: []string{"tag:exit"}, Hostinfo: &tailcfg.Hostinfo{}, + }, + } +} + +// findNodeByGivenName finds a node by its GivenName field. +func findNodeByGivenName(nodes types.Nodes, name string) *types.Node { + for _, n := range nodes { + if n.GivenName == name { + return n + } + } + + return nil +} + +// cmpOptions returns comparison options for FilterRule slices. +// It sorts SrcIPs and DstPorts to handle ordering differences. +func cmpOptions() []cmp.Option { + return []cmp.Option{ + cmpopts.SortSlices(func(a, b string) bool { return a < b }), + cmpopts.SortSlices(func(a, b tailcfg.NetPortRange) bool { + if a.IP != b.IP { + return a.IP < b.IP + } + + if a.Ports.First != b.Ports.First { + return a.Ports.First < b.Ports.First + } + + return a.Ports.Last < b.Ports.Last + }), + cmpopts.SortSlices(func(a, b int) bool { return a < b }), + } +} + +// aclTestFile represents the JSON structure of a captured ACL test file. +type aclTestFile struct { + TestID string `json:"test_id"` + Source string `json:"source"` // "tailscale_saas" or "headscale_adapted" + Error bool `json:"error"` + HeadscaleDiffers bool `json:"headscale_differs"` + ParentTest string `json:"parent_test"` + Input struct { + FullPolicy json.RawMessage `json:"full_policy"` + APIResponseCode int `json:"api_response_code"` + APIResponseBody *struct { + Message string `json:"message"` + } `json:"api_response_body"` + } `json:"input"` + Topology struct { + Nodes map[string]struct { + Hostname string `json:"hostname"` + Tags []string `json:"tags"` + IPv4 string `json:"ipv4"` + IPv6 string `json:"ipv6"` + User string `json:"user"` + } `json:"nodes"` + } `json:"topology"` + Captures map[string]struct { + PacketFilterRules json.RawMessage `json:"packet_filter_rules"` + } `json:"captures"` +} + +// loadACLTestFile loads and parses a single ACL test JSON file. +func loadACLTestFile(t *testing.T, path string) aclTestFile { + t.Helper() + + content, err := os.ReadFile(path) + require.NoError(t, err, "failed to read test file %s", path) + + var tf aclTestFile + + err = json.Unmarshal(content, &tf) + require.NoError(t, err, "failed to parse test file %s", path) + + return tf +} + +// aclSkipReasons documents WHY tests are expected to fail and WHAT needs to be +// implemented to fix them. Tests are grouped by root cause. +// +// Impact summary: +// +// SRCIPS_FORMAT - tests: SrcIPs use adapted format (100.64.0.0/10 vs partitioned CIDRs) +// DSTPORTS_FORMAT - tests: DstPorts IP format differences +// IPPROTO_FORMAT - tests: IPProto nil vs [6,17,1,58] +// IMPLEMENTATION_PENDING - tests: Not yet implemented in headscale +var aclSkipReasons = map[string]string{ + // Currently all tests are in the skip list because the ACL engine + // output format changed with the ResolvedAddresses refactor. + // Tests will be removed from this list as the implementation is + // updated to match the expected output. +} + +// TestACLCompat is a data-driven test that loads all ACL-*.json test files +// and compares headscale's ACL engine output against the expected behavior. +// +// Each JSON file contains: +// - A full policy with groups, tagOwners, hosts, and acls +// - For success cases: expected packet_filter_rules per node (5 nodes) +// - For error cases: expected error message +func TestACLCompat(t *testing.T) { + t.Parallel() + + files, err := filepath.Glob( + filepath.Join("testdata", "acl_results", "ACL-*.json"), + ) + require.NoError(t, err, "failed to glob test files") + require.NotEmpty( + t, + files, + "no ACL-*.json test files found in testdata/acl_results/", + ) + + t.Logf("Loaded %d ACL test files", len(files)) + + users := setupACLCompatUsers() + nodes := setupACLCompatNodes(users) + + for _, file := range files { + tf := loadACLTestFile(t, file) + + t.Run(tf.TestID, func(t *testing.T) { + t.Parallel() + + // Check skip list + if reason, ok := aclSkipReasons[tf.TestID]; ok { + t.Skipf( + "TODO: %s — see aclSkipReasons for details", + reason, + ) + + return + } + + if tf.Error { + testACLError(t, tf) + + return + } + + testACLSuccess(t, tf, users, nodes) + }) + } +} + +// testACLError verifies that an invalid policy produces the expected error. +func testACLError(t *testing.T, tf aclTestFile) { + t.Helper() + + policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy) + + pol, err := unmarshalPolicy(policyJSON) + if err != nil { + // Parse-time error — valid for some error tests + if tf.Input.APIResponseBody != nil { + wantMsg := tf.Input.APIResponseBody.Message + if wantMsg != "" { + assert.Contains( + t, + err.Error(), + wantMsg, + "%s: error message should contain expected substring", + tf.TestID, + ) + } + } + + return + } + + err = pol.validate() + if err != nil { + if tf.Input.APIResponseBody != nil { + wantMsg := tf.Input.APIResponseBody.Message + if wantMsg != "" { + // Allow partial match — headscale error messages differ + // from Tailscale's + errStr := err.Error() + if !strings.Contains(errStr, wantMsg) { + // Try matching key parts + matched := false + + for _, part := range []string{ + "autogroup:self", + "not valid on the src", + "port range", + "tag not found", + "undefined", + } { + if strings.Contains(wantMsg, part) && + strings.Contains(errStr, part) { + matched = true + + break + } + } + + if !matched { + t.Logf( + "%s: error message difference\n want (tailscale): %q\n got (headscale): %q", + tf.TestID, + wantMsg, + errStr, + ) + } + } + } + } + + return + } + + // For headscale_differs tests, headscale may accept what Tailscale rejects + if tf.HeadscaleDiffers { + t.Logf( + "%s: headscale accepts this policy (Tailscale rejects it)", + tf.TestID, + ) + + return + } + + t.Errorf( + "%s: expected error but policy parsed and validated successfully", + tf.TestID, + ) +} + +// testACLSuccess verifies that a valid policy produces the expected +// packet filter rules for each node. +func testACLSuccess( + t *testing.T, + tf aclTestFile, + users types.Users, + nodes types.Nodes, +) { + t.Helper() + + // Convert Tailscale SaaS user emails to headscale @example.com format. + policyJSON := convertPolicyUserEmails(tf.Input.FullPolicy) + + pol, err := unmarshalPolicy(policyJSON) + require.NoError( + t, + err, + "%s: policy should parse successfully", + tf.TestID, + ) + + err = pol.validate() + require.NoError( + t, + err, + "%s: policy should validate successfully", + tf.TestID, + ) + + for nodeName, capture := range tf.Captures { + t.Run(nodeName, func(t *testing.T) { + captureIsNull := len(capture.PacketFilterRules) == 0 || + string(capture.PacketFilterRules) == "null" //nolint:goconst + + node := findNodeByGivenName(nodes, nodeName) + if node == nil { + t.Skipf( + "node %s not found in test setup", + nodeName, + ) + + return + } + + // Compile headscale filter rules for this node + compiledRules, err := pol.compileFilterRulesForNode( + users, + node.View(), + nodes.ViewSlice(), + ) + require.NoError( + t, + err, + "%s/%s: failed to compile filter rules", + tf.TestID, + nodeName, + ) + + gotRules := policyutil.ReduceFilterRules( + node.View(), + compiledRules, + ) + + // Parse expected rules from JSON + var wantRules []tailcfg.FilterRule + if !captureIsNull { + err = json.Unmarshal( + capture.PacketFilterRules, + &wantRules, + ) + require.NoError( + t, + err, + "%s/%s: failed to unmarshal expected rules", + tf.TestID, + nodeName, + ) + } + + // Compare + opts := append( + cmpOptions(), + cmpopts.EquateEmpty(), + ) + if diff := cmp.Diff( + wantRules, + gotRules, + opts..., + ); diff != "" { + t.Errorf( + "%s/%s: filter rules mismatch (-want +got):\n%s", + tf.TestID, + nodeName, + diff, + ) + } + }) + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A01.json new file mode 100644 index 00000000..adfab5b5 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A01.json @@ -0,0 +1,283 @@ +{ + "test_id": "ACL-A01", + "timestamp": "2026-03-17T14:16:33Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A02.json new file mode 100644 index 00000000..ace18c56 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A02.json @@ -0,0 +1,315 @@ +{ + "test_id": "ACL-A02", + "timestamp": "2026-03-17T14:16:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A03.json new file mode 100644 index 00000000..bf4c52bb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A03.json @@ -0,0 +1,152 @@ +{ + "test_id": "ACL-A03", + "timestamp": "2026-03-17T14:16:54Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A04.json new file mode 100644 index 00000000..a0df000c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A04.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-A04", + "timestamp": "2026-03-17T14:17:04Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A05.json new file mode 100644 index 00000000..339e98c1 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A05.json @@ -0,0 +1,123 @@ +{ + "test_id": "ACL-A05", + "timestamp": "2026-03-17T14:17:15Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:internet:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A06.json new file mode 100644 index 00000000..c57dd1cf --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A06.json @@ -0,0 +1,198 @@ +{ + "test_id": "ACL-A06", + "timestamp": "2026-03-17T14:17:25Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:member:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A07.json new file mode 100644 index 00000000..44222cd5 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A07.json @@ -0,0 +1,208 @@ +{ + "test_id": "ACL-A07", + "timestamp": "2026-03-17T14:17:36Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*", "tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A08.json new file mode 100644 index 00000000..6e1cd16d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A08.json @@ -0,0 +1,248 @@ +{ + "test_id": "ACL-A08", + "timestamp": "2026-03-17T14:17:47Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:tagged:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A09.json new file mode 100644 index 00000000..0387fb85 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A09.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-A09", + "timestamp": "2026-03-17T14:17:57Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A10.json new file mode 100644 index 00000000..b0e730e3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A10.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-A10", + "timestamp": "2026-03-17T14:18:08Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A11.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A11.json new file mode 100644 index 00000000..d09858c3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A11.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-A11", + "timestamp": "2026-03-17T14:18:18Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a11.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A12.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A12.json new file mode 100644 index 00000000..cb1971df --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A12.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-A12", + "timestamp": "2026-03-17T14:18:28Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a12.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A13.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A13.json new file mode 100644 index 00000000..67d3f820 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A13.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-A13", + "timestamp": "2026-03-17T14:18:39Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a13.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:80-443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A14.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A14.json new file mode 100644 index 00000000..260728e2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A14.json @@ -0,0 +1,267 @@ +{ + "test_id": "ACL-A14", + "timestamp": "2026-03-17T14:18:49Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a14.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22,80,443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A15.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A15.json new file mode 100644 index 00000000..d1f3426b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A15.json @@ -0,0 +1,363 @@ +{ + "test_id": "ACL-A15", + "timestamp": "2026-03-17T14:19:00Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a15.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "autogroup:tagged"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A16.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A16.json new file mode 100644 index 00000000..39f5dd4f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A16.json @@ -0,0 +1,160 @@ +{ + "test_id": "ACL-A16", + "timestamp": "2026-03-17T14:19:10Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a16.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "autogroup:tagged"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-A17.json b/hscontrol/policy/v2/testdata/acl_results/ACL-A17.json new file mode 100644 index 00000000..829eabfc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-A17.json @@ -0,0 +1,280 @@ +{ + "test_id": "ACL-A17", + "timestamp": "2026-03-17T14:19:21Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_a17.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*", "tag:server:22", "autogroup:member:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH01.json new file mode 100644 index 00000000..bff0dd40 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH01.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-AH01", + "timestamp": "2026-03-17T14:19:31Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["internal", "subnet24"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "192.168.1.0/24"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH02.json new file mode 100644 index 00000000..bcc05bf1 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-AH02", + "timestamp": "2026-03-17T14:19:42Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["internal", "100.108.74.26"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "100.108.74.26"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH03.json new file mode 100644 index 00000000..8ed87a0e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH03.json @@ -0,0 +1,166 @@ +{ + "test_id": "ACL-AH03", + "timestamp": "2026-03-17T14:19:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["internal:22", "subnet24:80", "tag:server:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "10.0.0.0/8", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH04.json new file mode 100644 index 00000000..06a744b6 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH04.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-AH04", + "timestamp": "2026-03-17T14:20:02Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["internal", "10.0.0.0/8"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH05.json new file mode 100644 index 00000000..19009f65 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH05.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-AH05", + "timestamp": "2026-03-17T14:20:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["internal:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "10.0.0.0/8", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AH06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AH06.json new file mode 100644 index 00000000..1cbd99cb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AH06.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-AH06", + "timestamp": "2026-03-17T14:20:23Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ah06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["10.0.0.0/8:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "10.0.0.0/8", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR01.json new file mode 100644 index 00000000..9bc376c0 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR01.json @@ -0,0 +1,176 @@ +{ + "test_id": "ACL-AR01", + "timestamp": "2026-03-17T14:20:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80,443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR02.json new file mode 100644 index 00000000..333e9899 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR02.json @@ -0,0 +1,207 @@ +{ + "test_id": "ACL-AR02", + "timestamp": "2026-03-17T14:20:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80,443"] + }, + { + "action": "accept", + "src": ["*"], + "proto": "udp", + "dst": ["tag:server:53"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 53, + "Last": 53 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 53, + "Last": 53 + } + } + ], + "IPProto": [17] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR03.json new file mode 100644 index 00000000..0c84ef98 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR03.json @@ -0,0 +1,181 @@ +{ + "test_id": "ACL-AR03", + "timestamp": "2026-03-17T14:20:55Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR04.json new file mode 100644 index 00000000..42953d8a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR04.json @@ -0,0 +1,191 @@ +{ + "test_id": "ACL-AR04", + "timestamp": "2026-03-17T14:21:05Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:router"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.92.142.61", "fd7a:115c:a1e0::3e37:8e3d"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR05.json new file mode 100644 index 00000000..0ffaa3c1 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR05.json @@ -0,0 +1,205 @@ +{ + "test_id": "ACL-AR05", + "timestamp": "2026-03-17T14:21:16Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AR06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AR06.json new file mode 100644 index 00000000..97fd9f08 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AR06.json @@ -0,0 +1,172 @@ +{ + "test_id": "ACL-AR06", + "timestamp": "2026-03-17T14:21:26Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_ar06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT01.json new file mode 100644 index 00000000..2c972e7e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT01.json @@ -0,0 +1,315 @@ +{ + "test_id": "ACL-AT01", + "timestamp": "2026-03-17T14:21:36Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server", "tag:client", "tag:prod", "tag:router", "tag:exit"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT02.json new file mode 100644 index 00000000..bdc599df --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT02.json @@ -0,0 +1,248 @@ +{ + "test_id": "ACL-AT02", + "timestamp": "2026-03-17T14:21:47Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22", "tag:client:22", "tag:prod:22", "tag:router:22", "tag:exit:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT03.json new file mode 100644 index 00000000..92c2ef71 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT03.json @@ -0,0 +1,216 @@ +{ + "test_id": "ACL-AT03", + "timestamp": "2026-03-17T14:21:57Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server", "tag:client", "tag:prod", "tag:router", "tag:exit"], + "dst": ["autogroup:member:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT04.json new file mode 100644 index 00000000..5a0894b6 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT04.json @@ -0,0 +1,185 @@ +{ + "test_id": "ACL-AT04", + "timestamp": "2026-03-17T14:22:08Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT05.json new file mode 100644 index 00000000..9f606358 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT05.json @@ -0,0 +1,168 @@ +{ + "test_id": "ACL-AT05", + "timestamp": "2026-03-17T14:22:18Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:client:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AT06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AT06.json new file mode 100644 index 00000000..db101e99 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AT06.json @@ -0,0 +1,217 @@ +{ + "test_id": "ACL-AT06", + "timestamp": "2026-03-17T14:22:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_at06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:client:80"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + }, + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU01.json new file mode 100644 index 00000000..ad696e82 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU01.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-AU01", + "timestamp": "2026-03-17T14:22:39Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kristoffer@dalby.cc"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU02.json new file mode 100644 index 00000000..7f021094 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-AU02", + "timestamp": "2026-03-17T14:22:49Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["monitorpasskeykradalby@passkey"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU03.json new file mode 100644 index 00000000..eb0b26fb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU03.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-AU03", + "timestamp": "2026-03-17T14:23:00Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["tag:server:22", "tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "100.90.199.68", "fd7a:115c:a1e0::1737:7960", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "100.90.199.68", "fd7a:115c:a1e0::1737:7960", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU04.json new file mode 100644 index 00000000..61bb5ddd --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU04.json @@ -0,0 +1,173 @@ +{ + "test_id": "ACL-AU04", + "timestamp": "2026-03-17T14:23:10Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["group:developers:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU05.json new file mode 100644 index 00000000..63cc6805 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU05.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-AU05", + "timestamp": "2026-03-17T14:23:21Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["group:monitors:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-AU06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-AU06.json new file mode 100644 index 00000000..6bbeed3b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-AU06.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-AU06", + "timestamp": "2026-03-17T14:23:31Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_au06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins", "group:developers", "group:monitors"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C01.json new file mode 100644 index 00000000..633be674 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C01.json @@ -0,0 +1,204 @@ +{ + "test_id": "ACL-C01", + "timestamp": "2026-03-17T14:23:42Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C02.json new file mode 100644 index 00000000..cdba652c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C02.json @@ -0,0 +1,201 @@ +{ + "test_id": "ACL-C02", + "timestamp": "2026-03-17T14:23:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "autogroup:member"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C03.json new file mode 100644 index 00000000..71d12741 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C03.json @@ -0,0 +1,235 @@ +{ + "test_id": "ACL-C03", + "timestamp": "2026-03-17T14:24:03Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "tag:prod:5432", "webserver:80"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C04.json new file mode 100644 index 00000000..0b611ea0 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C04.json @@ -0,0 +1,238 @@ +{ + "test_id": "ACL-C04", + "timestamp": "2026-03-17T14:24:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:internet:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C05.json new file mode 100644 index 00000000..c5374597 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C05.json @@ -0,0 +1,388 @@ +{ + "test_id": "ACL-C05", + "timestamp": "2026-03-17T14:24:23Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": [ + "tag:server:22", + "tag:prod:5432", + "tag:client:80", + "tag:router:*", + "tag:exit:*", + "autogroup:member:443", + "autogroup:self:*" + ] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + }, + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + }, + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C06.json new file mode 100644 index 00000000..cd12e982 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C06.json @@ -0,0 +1,156 @@ +{ + "test_id": "ACL-C06", + "timestamp": "2026-03-17T14:24:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "tag:prod", "tag:server", "autogroup:member", "group:admins"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C07.json new file mode 100644 index 00000000..a80d3eab --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C07.json @@ -0,0 +1,200 @@ +{ + "test_id": "ACL-C07", + "timestamp": "2026-03-17T14:24:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:443"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:8080"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 8080, + "Last": 8080 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C08.json new file mode 100644 index 00000000..c3cbe486 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C08.json @@ -0,0 +1,248 @@ +{ + "test_id": "ACL-C08", + "timestamp": "2026-03-17T14:24:55Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22", "tag:prod:22", "tag:client:22", "tag:router:22", "tag:exit:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C09.json new file mode 100644 index 00000000..d7f5a557 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C09.json @@ -0,0 +1,287 @@ +{ + "test_id": "ACL-C09", + "timestamp": "2026-03-17T14:25:05Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:22"] + }, + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["group:developers"], + "dst": ["tag:router:*"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:internet:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "100.90.199.68", "fd7a:115c:a1e0::1737:7960", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-C10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-C10.json new file mode 100644 index 00000000..f2e7b7bc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-C10.json @@ -0,0 +1,400 @@ +{ + "test_id": "ACL-C10", + "timestamp": "2026-03-17T14:25:16Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_c10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:22", "tag:prod:5432"] + }, + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["autogroup:tagged:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D01.json new file mode 100644 index 00000000..c88b22a4 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D01.json @@ -0,0 +1,172 @@ +{ + "test_id": "ACL-D01", + "timestamp": "2026-03-17T14:25:26Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D02.json new file mode 100644 index 00000000..a399570e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D02.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-D02", + "timestamp": "2026-03-17T14:25:37Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "webserver:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D03.json new file mode 100644 index 00000000..5afeee24 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D03.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-D03", + "timestamp": "2026-03-17T14:25:47Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.108.74.26", "tag:server"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D04.json new file mode 100644 index 00000000..fcf31f23 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D04.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-D04", + "timestamp": "2026-03-17T14:25:57Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.108.74.26", "webserver"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D05.json new file mode 100644 index 00000000..7814df0e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D05.json @@ -0,0 +1,155 @@ +{ + "test_id": "ACL-D05", + "timestamp": "2026-03-17T14:26:08Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["100.108.74.26:22", "tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D06.json new file mode 100644 index 00000000..aabbfa10 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D06.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-D06", + "timestamp": "2026-03-17T14:26:18Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["100.108.74.26:22", "webserver:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D07.json new file mode 100644 index 00000000..028fe39d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D07.json @@ -0,0 +1,363 @@ +{ + "test_id": "ACL-D07", + "timestamp": "2026-03-17T14:26:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "autogroup:tagged"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-D08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-D08.json new file mode 100644 index 00000000..0e4e0fbc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-D08.json @@ -0,0 +1,202 @@ +{ + "test_id": "ACL-D08", + "timestamp": "2026-03-17T14:26:39Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_d08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["kratail2tid@passkey:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E01.json new file mode 100644 index 00000000..138f9d56 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E01.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-E01", + "timestamp": "2026-03-17T14:26:50Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.108.74.26"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E02.json new file mode 100644 index 00000000..1dcabc3d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E02.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-E02", + "timestamp": "2026-03-17T14:27:00Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E03.json new file mode 100644 index 00000000..bffcf22b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E03.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-E03", + "timestamp": "2026-03-17T14:27:11Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E04.json new file mode 100644 index 00000000..47976c18 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E04.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-E04", + "timestamp": "2026-03-17T14:27:21Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["100.108.74.26:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E05.json new file mode 100644 index 00000000..2195029c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E05.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-E05", + "timestamp": "2026-03-17T14:27:32Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E06.json new file mode 100644 index 00000000..557b2279 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E06.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-E06", + "timestamp": "2026-03-17T14:27:42Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["webserver:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E07.json new file mode 100644 index 00000000..9ce58537 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E07.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-E07", + "timestamp": "2026-03-17T14:27:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E08.json new file mode 100644 index 00000000..407badcc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E08.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-E08", + "timestamp": "2026-03-17T14:28:03Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-E09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-E09.json new file mode 100644 index 00000000..755ca138 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-E09.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-E09", + "timestamp": "2026-03-17T14:28:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_e09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey", "group:admins"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR01.json new file mode 100644 index 00000000..f327419b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR01.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR01", + "timestamp": "2026-03-17T14:28:24Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:nonexistent"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "src=tag not found: \"tag:nonexistent\"" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR02.json new file mode 100644 index 00000000..1eebf587 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR02.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR02", + "timestamp": "2026-03-17T14:28:24Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:self"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "\"autogroup:self\" not valid on the src side of a rule" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR03.json new file mode 100644 index 00000000..5c6a5100 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR03.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR03", + "timestamp": "2026-03-17T14:28:24Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "dst=\"autogroup:self\": port range \"self\": invalid first integer" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR04.json new file mode 100644 index 00000000..fd7387ee --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR04.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR04", + "timestamp": "2026-03-17T14:28:25Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:nonexistent"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "src=tag not found: \"tag:nonexistent\"" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR05.json new file mode 100644 index 00000000..105363fe --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR05.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR05", + "timestamp": "2026-03-17T14:28:25Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:nonexistent:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "dst=\"tag:nonexistent\": tag not found: \"tag:nonexistent\"" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR06.json new file mode 100644 index 00000000..aeb01305 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR06.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR06", + "timestamp": "2026-03-17T14:28:25Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "deny", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "action=\"deny\" is not supported" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR07.json new file mode 100644 index 00000000..669e7a06 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR07.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-ERR07", + "timestamp": "2026-03-17T14:28:29Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:ssh"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "dst=\"tag:server:ssh\": port range \"ssh\": invalid first integer" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR08.json new file mode 100644 index 00000000..f0abcb87 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR08.json @@ -0,0 +1,51 @@ +{ + "test_id": "ACL-ERR08", + "timestamp": "2026-03-17T14:28:34Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-ERR09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR09.json new file mode 100644 index 00000000..a617c402 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-ERR09.json @@ -0,0 +1,51 @@ +{ + "test_id": "ACL-ERR09", + "timestamp": "2026-03-17T14:28:39Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_err09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H01.json new file mode 100644 index 00000000..73dabb10 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H01.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-H01", + "timestamp": "2026-03-17T14:28:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["webserver:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H02.json new file mode 100644 index 00000000..57a1f5f3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H02.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-H02", + "timestamp": "2026-03-17T14:28:59Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H03.json new file mode 100644 index 00000000..db4af458 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H03.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-H03", + "timestamp": "2026-03-17T14:29:10Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["internal"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H04.json new file mode 100644 index 00000000..da7ee2b0 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H04.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-H04", + "timestamp": "2026-03-17T14:29:20Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["internal:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "10.0.0.0/8", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H05.json new file mode 100644 index 00000000..36a9b30f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H05.json @@ -0,0 +1,159 @@ +{ + "test_id": "ACL-H05", + "timestamp": "2026-03-17T14:29:31Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["webserver:22", "prodbox:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H06.json new file mode 100644 index 00000000..1529a1dd --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H06.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-H06", + "timestamp": "2026-03-17T14:29:41Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H07.json new file mode 100644 index 00000000..c8c0fd84 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H07.json @@ -0,0 +1,136 @@ +{ + "test_id": "ACL-H07", + "timestamp": "2026-03-17T14:29:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["webserver:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-H08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-H08.json new file mode 100644 index 00000000..a635f7c7 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-H08.json @@ -0,0 +1,123 @@ +{ + "test_id": "ACL-H08", + "timestamp": "2026-03-17T14:30:02Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_h08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["subnet24:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-K01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-K01.json new file mode 100644 index 00000000..cfc17a34 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-K01.json @@ -0,0 +1,172 @@ +{ + "test_id": "ACL-K01", + "timestamp": "2026-03-17T14:30:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_k01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": [ + "*", + "autogroup:member", + "autogroup:tagged", + "group:admins", + "tag:client", + "webserver", + "100.90.199.68" + ], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::/48", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-K02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-K02.json new file mode 100644 index 00000000..b9e10966 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-K02.json @@ -0,0 +1,226 @@ +{ + "test_id": "ACL-K02", + "timestamp": "2026-03-17T14:30:23Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_k02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": [ + "tag:server:22", + "tag:prod:5432", + "webserver:80", + "prodbox:443", + "group:admins:8080", + "kratail2tid@passkey:3000", + "100.108.74.26:9000" + ] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 9000, + "Last": 9000 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 3000, + "Last": 3000 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 3000, + "Last": 3000 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 8080, + "Last": 8080 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-K03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-K03.json new file mode 100644 index 00000000..d431edf3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-K03.json @@ -0,0 +1,374 @@ +{ + "test_id": "ACL-K03", + "timestamp": "2026-03-17T14:30:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_k03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": [ + "autogroup:member", + "autogroup:tagged", + "group:admins", + "group:developers", + "kratail2tid@passkey", + "tag:client", + "tag:prod", + "tag:server", + "webserver", + "prodbox" + ], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-K04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-K04.json new file mode 100644 index 00000000..e58a7e0b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-K04.json @@ -0,0 +1,278 @@ +{ + "test_id": "ACL-K04", + "timestamp": "2026-03-17T14:30:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_k04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": [ + "tag:server:22", + "tag:server:80", + "tag:server:443", + "tag:prod:5432", + "tag:prod:3306", + "tag:client:80", + "tag:client:443", + "webserver:8080", + "prodbox:8080" + ] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.83.200.69", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "100.103.8.15", + "Ports": { + "First": 3306, + "Last": 3306 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 3306, + "Last": 3306 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-K05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-K05.json new file mode 100644 index 00000000..3aaa7f39 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-K05.json @@ -0,0 +1,221 @@ +{ + "test_id": "ACL-K05", + "timestamp": "2026-03-17T14:30:54Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_k05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": [ + "autogroup:member", + "group:admins", + "kratail2tid@passkey", + "tag:client", + "tag:prod", + "100.83.200.69", + "100.103.8.15" + ], + "dst": ["tag:server:22", "webserver:80", "100.108.74.26:443", "group:admins:8080", "kratail2tid@passkey:9000"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 9000, + "Last": 9000 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 9000, + "Last": 9000 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 8080, + "Last": 8080 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M01.json new file mode 100644 index 00000000..7380851c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M01.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-M01", + "timestamp": "2026-03-17T14:31:05Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey", "tag:client", "group:monitors"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M02.json new file mode 100644 index 00000000..0dbced2d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M02", + "timestamp": "2026-03-17T14:31:15Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.90.199.68", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "100.90.199.68", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M03.json new file mode 100644 index 00000000..0632438a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M03.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M03", + "timestamp": "2026-03-17T14:31:26Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver", "tag:client"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M04.json new file mode 100644 index 00000000..b2f290d3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M04.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M04", + "timestamp": "2026-03-17T14:31:36Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "100.90.199.68", "fd7a:115c:a1e0::2d01:c747", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M05.json new file mode 100644 index 00000000..ee51c3a6 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M05.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M05", + "timestamp": "2026-03-17T14:31:47Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey", "group:monitors"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "100.90.199.68", "fd7a:115c:a1e0::2d01:c747", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M06.json new file mode 100644 index 00000000..892f019b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M06.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-M06", + "timestamp": "2026-03-17T14:31:57Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "100.83.200.69", + "fd7a:115c:a1e0::/48", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M07.json new file mode 100644 index 00000000..25766123 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M07.json @@ -0,0 +1,180 @@ +{ + "test_id": "ACL-M07", + "timestamp": "2026-03-17T14:32:08Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "tag:client"], + "dst": ["tag:server:22,80,443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M08.json new file mode 100644 index 00000000..d78dcf3c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M08.json @@ -0,0 +1,152 @@ +{ + "test_id": "ACL-M08", + "timestamp": "2026-03-17T14:32:18Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "tag:client"], + "dst": ["tag:server:80-443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.83.200.69", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M09.json new file mode 100644 index 00000000..4cfc286b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M09.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M09", + "timestamp": "2026-03-17T14:32:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "internal"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["10.0.0.0/8", "100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-M10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-M10.json new file mode 100644 index 00000000..1f5dcae2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-M10.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-M10", + "timestamp": "2026-03-17T14:32:39Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_m10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.92.142.61", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "100.92.142.61", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR01.json new file mode 100644 index 00000000..f62a23c9 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR01.json @@ -0,0 +1,168 @@ +{ + "test_id": "ACL-MR01", + "timestamp": "2026-03-17T14:32:50Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR02.json new file mode 100644 index 00000000..c305ac4f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR02.json @@ -0,0 +1,162 @@ +{ + "test_id": "ACL-MR02", + "timestamp": "2026-03-17T14:33:00Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR03.json new file mode 100644 index 00000000..ea687121 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR03.json @@ -0,0 +1,167 @@ +{ + "test_id": "ACL-MR03", + "timestamp": "2026-03-17T14:33:10Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR04.json new file mode 100644 index 00000000..5a7d1127 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR04.json @@ -0,0 +1,162 @@ +{ + "test_id": "ACL-MR04", + "timestamp": "2026-03-17T14:33:21Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR05.json new file mode 100644 index 00000000..7196cd13 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR05.json @@ -0,0 +1,167 @@ +{ + "test_id": "ACL-MR05", + "timestamp": "2026-03-17T14:33:31Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["group:admins:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["kratail2tid@passkey:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR06.json new file mode 100644 index 00000000..07fc9759 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR06.json @@ -0,0 +1,202 @@ +{ + "test_id": "ACL-MR06", + "timestamp": "2026-03-17T14:33:42Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["autogroup:member:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["group:admins:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR07.json new file mode 100644 index 00000000..03180abe --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR07.json @@ -0,0 +1,217 @@ +{ + "test_id": "ACL-MR07", + "timestamp": "2026-03-17T14:33:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22", "tag:prod:5432"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80", "tag:router:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR08.json new file mode 100644 index 00000000..2c6c0ca7 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR08.json @@ -0,0 +1,191 @@ +{ + "test_id": "ACL-MR08", + "timestamp": "2026-03-17T14:34:03Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["tag:router"], + "dst": ["tag:server:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.92.142.61", "fd7a:115c:a1e0::3e37:8e3d"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR09.json new file mode 100644 index 00000000..b92f3a43 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR09.json @@ -0,0 +1,193 @@ +{ + "test_id": "ACL-MR09", + "timestamp": "2026-03-17T14:34:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR10.json new file mode 100644 index 00000000..185463eb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR10.json @@ -0,0 +1,193 @@ +{ + "test_id": "ACL-MR10", + "timestamp": "2026-03-17T14:34:23Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:router:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR11.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR11.json new file mode 100644 index 00000000..958cd1dd --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR11.json @@ -0,0 +1,228 @@ +{ + "test_id": "ACL-MR11", + "timestamp": "2026-03-17T14:34:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr11.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:member:22"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["group:admins:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR12.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR12.json new file mode 100644 index 00000000..242b3c8e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR12.json @@ -0,0 +1,162 @@ +{ + "test_id": "ACL-MR12", + "timestamp": "2026-03-17T14:34:44Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr12.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["kratail2tid@passkey:22"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["kratail2tid@passkey:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR13.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR13.json new file mode 100644 index 00000000..00d77deb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR13.json @@ -0,0 +1,378 @@ +{ + "test_id": "ACL-MR13", + "timestamp": "2026-03-17T14:34:55Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr13.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["autogroup:tagged:22"] + }, + { + "action": "accept", + "src": ["tag:client", "tag:prod"], + "dst": ["autogroup:tagged:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR14.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR14.json new file mode 100644 index 00000000..d3008297 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR14.json @@ -0,0 +1,560 @@ +{ + "test_id": "ACL-MR14", + "timestamp": "2026-03-17T14:35:05Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr14.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "autogroup:tagged"], + "dst": ["autogroup:member:22", "autogroup:tagged:80"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["*:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.103.90.82", + "100.108.74.26", + "100.110.121.96", + "100.83.200.69", + "100.85.66.106", + "100.90.199.68", + "100.92.142.61", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::9e37:5a52", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR15.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR15.json new file mode 100644 index 00000000..b615ead7 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR15.json @@ -0,0 +1,291 @@ +{ + "test_id": "ACL-MR15", + "timestamp": "2026-03-17T14:35:16Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr15.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:*"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR16.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR16.json new file mode 100644 index 00000000..502aed9e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR16.json @@ -0,0 +1,305 @@ +{ + "test_id": "ACL-MR16", + "timestamp": "2026-03-17T14:35:26Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr16.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["*:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR17.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR17.json new file mode 100644 index 00000000..185d6d4e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR17.json @@ -0,0 +1,246 @@ +{ + "test_id": "ACL-MR17", + "timestamp": "2026-03-17T14:35:37Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr17.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["*:*"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR18.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR18.json new file mode 100644 index 00000000..15b46c88 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR18.json @@ -0,0 +1,318 @@ +{ + "test_id": "ACL-MR18", + "timestamp": "2026-03-17T14:35:47Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr18.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22", "tag:prod:5432", "tag:client:80"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80", "*:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR19.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR19.json new file mode 100644 index 00000000..0b8dce19 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR19.json @@ -0,0 +1,472 @@ +{ + "test_id": "ACL-MR19", + "timestamp": "2026-03-17T14:35:58Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr19.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["*:*"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR20.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR20.json new file mode 100644 index 00000000..3b7550fe --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR20.json @@ -0,0 +1,175 @@ +{ + "test_id": "ACL-MR20", + "timestamp": "2026-03-17T14:36:08Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr20.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "group:admins", "kratail2tid@passkey"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:server", "webserver", "100.108.74.26"], + "dst": ["group:admins:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR21.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR21.json new file mode 100644 index 00000000..0656ffb7 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR21.json @@ -0,0 +1,226 @@ +{ + "test_id": "ACL-MR21", + "timestamp": "2026-03-17T14:36:18Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr21.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:client:80"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["webserver:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR22.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR22.json new file mode 100644 index 00000000..6c5306bb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR22.json @@ -0,0 +1,217 @@ +{ + "test_id": "ACL-MR22", + "timestamp": "2026-03-17T14:36:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr22.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:router:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["webserver:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["prodbox:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MR23.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MR23.json new file mode 100644 index 00000000..e83b49ff --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MR23.json @@ -0,0 +1,456 @@ +{ + "test_id": "ACL-MR23", + "timestamp": "2026-03-17T14:36:39Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mr23.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:client:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:prod:22"] + }, + { + "action": "accept", + "src": ["tag:router"], + "dst": ["tag:router:22"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["*:80"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:member:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.92.142.61", "fd7a:115c:a1e0::3e37:8e3d"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU01.json new file mode 100644 index 00000000..274b48ff --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU01.json @@ -0,0 +1,167 @@ +{ + "test_id": "ACL-MU01", + "timestamp": "2026-03-17T14:36:50Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["kristoffer@dalby.cc"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU02.json new file mode 100644 index 00000000..a630277e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU02.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-MU02", + "timestamp": "2026-03-17T14:37:00Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU03.json new file mode 100644 index 00000000..9598bdfb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU03.json @@ -0,0 +1,168 @@ +{ + "test_id": "ACL-MU03", + "timestamp": "2026-03-17T14:37:11Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["group:monitors"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "100.90.199.68", "fd7a:115c:a1e0::1737:7960", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU04.json new file mode 100644 index 00000000..fca1aeda --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU04.json @@ -0,0 +1,266 @@ +{ + "test_id": "ACL-MU04", + "timestamp": "2026-03-17T14:37:21Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:member:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU05.json new file mode 100644 index 00000000..420d204b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU05.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-MU05", + "timestamp": "2026-03-17T14:37:32Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["kratail2tid@passkey:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU06.json new file mode 100644 index 00000000..355a542d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU06.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-MU06", + "timestamp": "2026-03-17T14:37:42Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["kristoffer@dalby.cc:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU07.json new file mode 100644 index 00000000..1edcde76 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU07.json @@ -0,0 +1,283 @@ +{ + "test_id": "ACL-MU07", + "timestamp": "2026-03-17T14:37:53Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey", "kristoffer@dalby.cc", "monitorpasskeykradalby@passkey"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-MU08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-MU08.json new file mode 100644 index 00000000..fad93668 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-MU08.json @@ -0,0 +1,198 @@ +{ + "test_id": "ACL-MU08", + "timestamp": "2026-03-17T14:38:03Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_mu08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["kratail2tid@passkey:22", "kristoffer@dalby.cc:22", "monitorpasskeykradalby@passkey:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-O01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-O01.json new file mode 100644 index 00000000..90b8de0b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-O01.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-O01", + "timestamp": "2026-03-17T14:38:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_o01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "tag:prod"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-O02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-O02.json new file mode 100644 index 00000000..7ea0f912 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-O02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-O02", + "timestamp": "2026-03-17T14:38:24Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_o02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:prod", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-O03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-O03.json new file mode 100644 index 00000000..ab71d000 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-O03.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-O03", + "timestamp": "2026-03-17T14:38:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_o03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-O04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-O04.json new file mode 100644 index 00000000..262bea57 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-O04.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-O04", + "timestamp": "2026-03-17T14:38:45Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_o04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:5432", "tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P01.json new file mode 100644 index 00000000..c6bec53e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P01.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-P01", + "timestamp": "2026-03-17T14:38:55Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P02.json new file mode 100644 index 00000000..d3ebd0c2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P02.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-P02", + "timestamp": "2026-03-17T14:39:06Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:80-443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P03.json new file mode 100644 index 00000000..595084be --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P03.json @@ -0,0 +1,176 @@ +{ + "test_id": "ACL-P03", + "timestamp": "2026-03-17T14:39:16Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22,80,443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P04.json new file mode 100644 index 00000000..0b91c36a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P04.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-P04", + "timestamp": "2026-03-17T14:39:27Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"], + "proto": "tcp" + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ], + "IPProto": [6] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P05.json new file mode 100644 index 00000000..57d7bbc2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P05.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-P05", + "timestamp": "2026-03-17T14:39:37Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:53"], + "proto": "udp" + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 53, + "Last": 53 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 53, + "Last": 53 + } + } + ], + "IPProto": [17] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-P06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-P06.json new file mode 100644 index 00000000..88baebe2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-P06.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-P06", + "timestamp": "2026-03-17T14:39:48Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_p06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:*"], + "proto": "1" + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ], + "IPProto": [1] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-PF01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-PF01.json new file mode 100644 index 00000000..390cf539 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-PF01.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-PF01", + "timestamp": "2026-03-17T14:39:58Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_pf01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-PF02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-PF02.json new file mode 100644 index 00000000..29d83e0f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-PF02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-PF02", + "timestamp": "2026-03-17T14:40:09Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_pf02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80-443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-PF03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-PF03.json new file mode 100644 index 00000000..dbba01ea --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-PF03.json @@ -0,0 +1,171 @@ +{ + "test_id": "ACL-PF03", + "timestamp": "2026-03-17T14:40:19Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_pf03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22,80,443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-PF04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-PF04.json new file mode 100644 index 00000000..5bc9f695 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-PF04.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-PF04", + "timestamp": "2026-03-17T14:40:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_pf04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-PF05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-PF05.json new file mode 100644 index 00000000..af688736 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-PF05.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-PF05", + "timestamp": "2026-03-17T14:40:40Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_pf05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:1-65535"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 1, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 1, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R01.json new file mode 100644 index 00000000..c799d2e9 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R01.json @@ -0,0 +1,167 @@ +{ + "test_id": "ACL-R01", + "timestamp": "2026-03-17T14:40:50Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R02.json new file mode 100644 index 00000000..3b530492 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R02.json @@ -0,0 +1,168 @@ +{ + "test_id": "ACL-R02", + "timestamp": "2026-03-17T14:41:01Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R03.json new file mode 100644 index 00000000..6f5639b3 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R03.json @@ -0,0 +1,162 @@ +{ + "test_id": "ACL-R03", + "timestamp": "2026-03-17T14:41:11Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R04.json new file mode 100644 index 00000000..4b5edc4a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R04.json @@ -0,0 +1,167 @@ +{ + "test_id": "ACL-R04", + "timestamp": "2026-03-17T14:41:22Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R05.json new file mode 100644 index 00000000..68f61569 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R05.json @@ -0,0 +1,291 @@ +{ + "test_id": "ACL-R05", + "timestamp": "2026-03-17T14:41:32Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:*"] + }, + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R06.json new file mode 100644 index 00000000..dc6756dc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R06.json @@ -0,0 +1,191 @@ +{ + "test_id": "ACL-R06", + "timestamp": "2026-03-17T14:41:43Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:server:80"] + }, + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R07.json new file mode 100644 index 00000000..248f2577 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R07.json @@ -0,0 +1,240 @@ +{ + "test_id": "ACL-R07", + "timestamp": "2026-03-17T14:41:53Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R08.json new file mode 100644 index 00000000..feef997c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R08.json @@ -0,0 +1,193 @@ +{ + "test_id": "ACL-R08", + "timestamp": "2026-03-17T14:42:04Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + }, + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:prod:5432"] + }, + { + "action": "accept", + "src": ["tag:prod"], + "dst": ["tag:client:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R09.json new file mode 100644 index 00000000..7241e609 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R09.json @@ -0,0 +1,215 @@ +{ + "test_id": "ACL-R09", + "timestamp": "2026-03-17T14:42:14Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-R10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-R10.json new file mode 100644 index 00000000..a9427763 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-R10.json @@ -0,0 +1,313 @@ +{ + "test_id": "ACL-R10", + "timestamp": "2026-03-17T14:42:25Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_r10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:tagged:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.85.66.106", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::7c37:426a", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS01.json new file mode 100644 index 00000000..edae2b34 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS01.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-RS01", + "timestamp": "2026-03-17T14:42:35Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "group:admins", "group:developers", "kratail2tid@passkey", "100.90.199.68"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.90.82", + "100.110.121.96", + "100.90.199.68", + "fd7a:115c:a1e0::1737:7960", + "fd7a:115c:a1e0::2d01:c747", + "fd7a:115c:a1e0::9e37:5a52" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS02.json new file mode 100644 index 00000000..fdf25bbc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-RS02", + "timestamp": "2026-03-17T14:42:45Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server", "webserver", "100.108.74.26"], + "dst": ["tag:client:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.83.200.69", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::c537:c845", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS03.json new file mode 100644 index 00000000..81334e8a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS03.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-RS03", + "timestamp": "2026-03-17T14:42:56Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:prod", "prodbox", "100.103.8.15"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "fd7a:115c:a1e0::5b37:80f"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS04.json new file mode 100644 index 00000000..837fcf09 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS04.json @@ -0,0 +1,216 @@ +{ + "test_id": "ACL-RS04", + "timestamp": "2026-03-17T14:43:06Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged", "tag:server", "tag:client", "tag:prod", "tag:router", "tag:exit"], + "dst": ["autogroup:member:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS05.json new file mode 100644 index 00000000..f41cf10e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS05.json @@ -0,0 +1,157 @@ +{ + "test_id": "ACL-RS05", + "timestamp": "2026-03-17T14:43:17Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "webserver:22", "100.108.74.26:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS06.json new file mode 100644 index 00000000..fd1cd5cb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS06.json @@ -0,0 +1,198 @@ +{ + "test_id": "ACL-RS06", + "timestamp": "2026-03-17T14:43:27Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["group:admins:22", "group:developers:22", "kratail2tid@passkey:22", "100.90.199.68:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-RS07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-RS07.json new file mode 100644 index 00000000..3566c741 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-RS07.json @@ -0,0 +1,185 @@ +{ + "test_id": "ACL-RS07", + "timestamp": "2026-03-17T14:43:38Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_rs07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "tag:server:80", "tag:server:443", "webserver:8080", "100.108.74.26:9000"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 8080, + "Last": 8080 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 443, + "Last": 443 + } + }, + { + "IP": "100.108.74.26", + "Ports": { + "First": 9000, + "Last": 9000 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S01.json new file mode 100644 index 00000000..48150bec --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S01.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-S01", + "timestamp": "2026-03-17T14:43:48Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S02.json new file mode 100644 index 00000000..91a1343a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S02.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-S02", + "timestamp": "2026-03-17T14:43:59Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S03.json new file mode 100644 index 00000000..08ca1bfe --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S03.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-S03", + "timestamp": "2026-03-17T14:44:09Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S04.json new file mode 100644 index 00000000..7e6119a2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S04.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-S04", + "timestamp": "2026-03-17T14:44:20Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_s04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S05.json new file mode 100644 index 00000000..45daa0a7 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S05.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-S05", + "timestamp": "2026-03-17T14:44:20Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_s05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.90.199.68"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S06.json new file mode 100644 index 00000000..a5508ed5 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S06.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-S06", + "timestamp": "2026-03-17T14:44:20Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_s06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S07.json new file mode 100644 index 00000000..fcb5b657 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S07.json @@ -0,0 +1,213 @@ +{ + "test_id": "ACL-S07", + "timestamp": "2026-03-17T14:44:20Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S08.json new file mode 100644 index 00000000..c54f589d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S08.json @@ -0,0 +1,255 @@ +{ + "test_id": "ACL-S08", + "timestamp": "2026-03-17T14:44:31Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*", "autogroup:member:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + }, + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S09.json new file mode 100644 index 00000000..4a0df20c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S09.json @@ -0,0 +1,225 @@ +{ + "test_id": "ACL-S09", + "timestamp": "2026-03-17T14:44:41Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22", "autogroup:self:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-S10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-S10.json new file mode 100644 index 00000000..2d560805 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-S10.json @@ -0,0 +1,230 @@ +{ + "test_id": "ACL-S10", + "timestamp": "2026-03-17T14:44:52Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_s10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF01.json new file mode 100644 index 00000000..cadc25b9 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF01.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-SF01", + "timestamp": "2026-03-17T14:45:02Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF02.json new file mode 100644 index 00000000..6c741acd --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF02.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-SF02", + "timestamp": "2026-03-17T14:45:13Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF03.json new file mode 100644 index 00000000..91a41445 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF03.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-SF03", + "timestamp": "2026-03-17T14:45:23Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_sf03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF04.json new file mode 100644 index 00000000..75219abd --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF04.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-SF04", + "timestamp": "2026-03-17T14:45:23Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_sf04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["webserver"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF05.json new file mode 100644 index 00000000..07e9da1b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF05.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-SF05", + "timestamp": "2026-03-17T14:45:24Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_sf05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.90.199.68"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF06.json new file mode 100644 index 00000000..4d153360 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF06.json @@ -0,0 +1,208 @@ +{ + "test_id": "ACL-SF06", + "timestamp": "2026-03-17T14:45:24Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*", "tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF07.json new file mode 100644 index 00000000..fbdef2bb --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF07.json @@ -0,0 +1,207 @@ +{ + "test_id": "ACL-SF07", + "timestamp": "2026-03-17T14:45:34Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:*", "group:admins:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF08.json new file mode 100644 index 00000000..65c76d48 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF08.json @@ -0,0 +1,46 @@ +{ + "test_id": "ACL-SF08", + "timestamp": "2026-03-17T14:45:45Z", + "error": true, + "input": { + "policy_file": "acl_policies/acl_sf08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:member", "tag:client"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 400, + "api_response_body": { "message": "autogroup:self can only be used with users, groups, or supported autogroups" } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF09.json new file mode 100644 index 00000000..3604b3f6 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF09.json @@ -0,0 +1,230 @@ +{ + "test_id": "ACL-SF09", + "timestamp": "2026-03-17T14:45:45Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22"] + }, + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF10.json new file mode 100644 index 00000000..9f6a7ffc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF10.json @@ -0,0 +1,225 @@ +{ + "test_id": "ACL-SF10", + "timestamp": "2026-03-17T14:45:55Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22", "autogroup:self:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.110.121.96", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.103.90.82", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "100.90.199.68", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF11.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF11.json new file mode 100644 index 00000000..0562494b --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF11.json @@ -0,0 +1,207 @@ +{ + "test_id": "ACL-SF11", + "timestamp": "2026-03-17T14:46:06Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf11.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["autogroup:self:22", "kratail2tid@passkey:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + }, + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF12.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF12.json new file mode 100644 index 00000000..235a791f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF12.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-SF12", + "timestamp": "2026-03-17T14:46:16Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf12.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kristoffer@dalby.cc"], + "dst": ["autogroup:self:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "100.110.121.96", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::1737:7960", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-SF13.json b/hscontrol/policy/v2/testdata/acl_results/ACL-SF13.json new file mode 100644 index 00000000..2dfbe83e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-SF13.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-SF13", + "timestamp": "2026-03-17T14:46:27Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_sf13.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:monitors"], + "dst": ["autogroup:self:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.103.90.82", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::9e37:5a52", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T01.json new file mode 100644 index 00000000..7290ab3c --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T01.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-T01", + "timestamp": "2026-03-17T14:46:37Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T02.json new file mode 100644 index 00000000..fef73138 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T02.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-T02", + "timestamp": "2026-03-17T14:46:48Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T03.json new file mode 100644 index 00000000..c3e1e872 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T03.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-T03", + "timestamp": "2026-03-17T14:46:58Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "tag:prod"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.8.15", "100.83.200.69", "fd7a:115c:a1e0::5b37:80f", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T04.json new file mode 100644 index 00000000..36751d45 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T04.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-T04", + "timestamp": "2026-03-17T14:47:09Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T05.json new file mode 100644 index 00000000..b2998a0a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T05.json @@ -0,0 +1,183 @@ +{ + "test_id": "ACL-T05", + "timestamp": "2026-03-17T14:47:19Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["tag:server:22", "tag:prod:5432", "tag:router:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 80, + "Last": 80 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T06.json new file mode 100644 index 00000000..e68913a6 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T06.json @@ -0,0 +1,154 @@ +{ + "test_id": "ACL-T06", + "timestamp": "2026-03-17T14:47:29Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["autogroup:tagged"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "100.85.66.106", + "100.92.142.61", + "fd7a:115c:a1e0::3e37:8e3d", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::7c37:426a", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T07.json new file mode 100644 index 00000000..8c453671 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T07.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-T07", + "timestamp": "2026-03-17T14:47:40Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:server"], + "dst": ["tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.108.74.26", "fd7a:115c:a1e0::b901:4a87"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T08.json new file mode 100644 index 00000000..3ad4cf0f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T08.json @@ -0,0 +1,150 @@ +{ + "test_id": "ACL-T08", + "timestamp": "2026-03-17T14:47:50Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client", "tag:server", "tag:prod"], + "dst": ["tag:router:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "100.103.8.15", + "100.108.74.26", + "100.83.200.69", + "fd7a:115c:a1e0::5b37:80f", + "fd7a:115c:a1e0::b901:4a87", + "fd7a:115c:a1e0::c537:c845" + ], + "DstPorts": [ + { + "IP": "100.92.142.61", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::3e37:8e3d", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T09.json new file mode 100644 index 00000000..e61ed893 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T09.json @@ -0,0 +1,136 @@ +{ + "test_id": "ACL-T09", + "timestamp": "2026-03-17T14:48:01Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["tag:client"], + "dst": ["100.108.74.26:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-T10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-T10.json new file mode 100644 index 00000000..4089db74 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-T10.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-T10", + "timestamp": "2026-03-17T14:48:11Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_t10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.83.200.69"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U01.json new file mode 100644 index 00000000..bb3b29e2 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U01.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-U01", + "timestamp": "2026-03-17T14:48:22Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U02.json new file mode 100644 index 00000000..52412106 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U02.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-U02", + "timestamp": "2026-03-17T14:48:32Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["kratail2tid@passkey:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U03.json new file mode 100644 index 00000000..61f67569 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U03.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-U03", + "timestamp": "2026-03-17T14:48:43Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U04.json new file mode 100644 index 00000000..096ca91d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U04.json @@ -0,0 +1,148 @@ +{ + "test_id": "ACL-U04", + "timestamp": "2026-03-17T14:48:53Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["group:admins:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.90.199.68", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::2d01:c747", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U05.json new file mode 100644 index 00000000..cb44017e --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U05.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-U05", + "timestamp": "2026-03-17T14:49:03Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:developers"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "100.90.199.68", "fd7a:115c:a1e0::1737:7960", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U06.json new file mode 100644 index 00000000..98aa256d --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U06.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-U06", + "timestamp": "2026-03-17T14:49:14Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U07.json new file mode 100644 index 00000000..d3fbe05f --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U07.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-U07", + "timestamp": "2026-03-17T14:49:24Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kristoffer@dalby.cc"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.110.121.96", "fd7a:115c:a1e0::1737:7960"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U08.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U08.json new file mode 100644 index 00000000..39022a55 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U08.json @@ -0,0 +1,163 @@ +{ + "test_id": "ACL-U08", + "timestamp": "2026-03-17T14:49:35Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u08.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins"], + "dst": ["tag:server:22", "tag:prod:5432"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.103.8.15", + "Ports": { + "First": 5432, + "Last": 5432 + } + }, + { + "IP": "fd7a:115c:a1e0::5b37:80f", + "Ports": { + "First": 5432, + "Last": 5432 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68", "fd7a:115c:a1e0::2d01:c747"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U09.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U09.json new file mode 100644 index 00000000..4a0e1828 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U09.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-U09", + "timestamp": "2026-03-17T14:49:45Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u09.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:monitors"], + "dst": ["tag:server:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.103.90.82", "fd7a:115c:a1e0::9e37:5a52"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U10.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U10.json new file mode 100644 index 00000000..9f35a5dc --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U10.json @@ -0,0 +1,123 @@ +{ + "test_id": "ACL-U10", + "timestamp": "2026-03-17T14:49:56Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u10.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:empty"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U11.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U11.json new file mode 100644 index 00000000..cd170e27 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U11.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-U11", + "timestamp": "2026-03-17T14:50:06Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u11.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["kratail2tid@passkey", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "100.90.199.68", "fd7a:115c:a1e0::2d01:c747", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-U12.json b/hscontrol/policy/v2/testdata/acl_results/ACL-U12.json new file mode 100644 index 00000000..f61bc2b8 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-U12.json @@ -0,0 +1,143 @@ +{ + "test_id": "ACL-U12", + "timestamp": "2026-03-17T14:50:17Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_u12.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["group:admins", "tag:client"], + "dst": ["tag:server:22"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.83.200.69", "100.90.199.68", "fd7a:115c:a1e0::2d01:c747", "fd7a:115c:a1e0::c537:c845"], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 22, + "Last": 22 + } + }, + { + "IP": "fd7a:115c:a1e0::b901:4a87", + "Ports": { + "First": 22, + "Last": 22 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W01.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W01.json new file mode 100644 index 00000000..d4a5bb63 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W01.json @@ -0,0 +1,267 @@ +{ + "test_id": "ACL-W01", + "timestamp": "2026-03-17T14:50:27Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w01.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W02.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W02.json new file mode 100644 index 00000000..35242597 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W02.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-W02", + "timestamp": "2026-03-17T14:50:38Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w02.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.90.199.68"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.90.199.68"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W03.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W03.json new file mode 100644 index 00000000..6c1cc135 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W03.json @@ -0,0 +1,227 @@ +{ + "test_id": "ACL-W03", + "timestamp": "2026-03-17T14:50:48Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w03.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["100.64.0.0/16"], + "dst": ["*:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": ["100.64.0.0/16"], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W04.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W04.json new file mode 100644 index 00000000..686eb622 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W04.json @@ -0,0 +1,141 @@ +{ + "test_id": "ACL-W04", + "timestamp": "2026-03-17T14:50:59Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w04.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["100.108.74.26:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "100.108.74.26", + "Ports": { + "First": 0, + "Last": 65535 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W05.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W05.json new file mode 100644 index 00000000..dbd4ba67 --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W05.json @@ -0,0 +1,123 @@ +{ + "test_id": "ACL-W05", + "timestamp": "2026-03-17T14:51:09Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w05.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["100.64.0.0/12:*"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": null + }, + "subnet-router": { + "packet_filter_rules": null + }, + "tagged-client": { + "packet_filter_rules": null + }, + "tagged-prod": { + "packet_filter_rules": null + }, + "tagged-server": { + "packet_filter_rules": null + }, + "user-kris": { + "packet_filter_rules": null + }, + "user-mon": { + "packet_filter_rules": null + }, + "user1": { + "packet_filter_rules": null + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W06.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W06.json new file mode 100644 index 00000000..6980de0a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W06.json @@ -0,0 +1,267 @@ +{ + "test_id": "ACL-W06", + "timestamp": "2026-03-17T14:51:20Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w06.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:80"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 80, + "Last": 80 + } + } + ] + } + ] + } + } +} diff --git a/hscontrol/policy/v2/testdata/acl_results/ACL-W07.json b/hscontrol/policy/v2/testdata/acl_results/ACL-W07.json new file mode 100644 index 00000000..6650ca3a --- /dev/null +++ b/hscontrol/policy/v2/testdata/acl_results/ACL-W07.json @@ -0,0 +1,267 @@ +{ + "test_id": "ACL-W07", + "timestamp": "2026-03-17T14:51:30Z", + "propagation_wait_seconds": 10, + "input": { + "policy_file": "acl_policies/acl_w07.json", + "full_policy": { + "groups": { + "group:admins": ["kratail2tid@passkey"], + "group:developers": ["kristoffer@dalby.cc", "kratail2tid@passkey"], + "group:monitors": ["monitorpasskeykradalby@passkey"], + "group:empty": [] + }, + "tagOwners": { + "tag:server": ["kratail2tid@passkey"], + "tag:prod": ["kratail2tid@passkey"], + "tag:client": ["kratail2tid@passkey"], + "tag:router": ["kratail2tid@passkey"], + "tag:exit": ["kratail2tid@passkey"] + }, + "hosts": { + "webserver": "100.108.74.26", + "prodbox": "100.103.8.15", + "internal": "10.0.0.0/8", + "subnet24": "192.168.1.0/24" + }, + "autoApprovers": { + "routes": { + "10.33.0.0/16": ["tag:router"], + "0.0.0.0/0": ["tag:exit"], + "::/0": ["tag:exit"] + } + }, + "acls": [ + { + "action": "accept", + "src": ["*"], + "dst": ["*:443"] + } + ] + }, + "api_endpoint": "https://api.tailscale.com/api/v2/tailnet/kratail2tid%40passkey/acl", + "api_response_code": 200 + }, + "topology": { + "nodes": { + "exit-node": { + "hostname": "exit-node", + "tags": ["tag:exit"], + "ipv4": "100.85.66.106", + "ipv6": "fd7a:115c:a1e0::7c37:426a" + }, + "subnet-router": { + "hostname": "subnet-router", + "tags": ["tag:router"], + "ipv4": "100.92.142.61", + "ipv6": "fd7a:115c:a1e0::3e37:8e3d" + }, + "tagged-client": { + "hostname": "tagged-client", + "tags": ["tag:client"], + "ipv4": "100.83.200.69", + "ipv6": "fd7a:115c:a1e0::c537:c845" + }, + "tagged-prod": { + "hostname": "tagged-prod", + "tags": ["tag:prod"], + "ipv4": "100.103.8.15", + "ipv6": "fd7a:115c:a1e0::5b37:80f" + }, + "tagged-server": { + "hostname": "tagged-server", + "tags": ["tag:server"], + "ipv4": "100.108.74.26", + "ipv6": "fd7a:115c:a1e0::b901:4a87" + }, + "user-kris": { + "hostname": "user-kris", + "tags": [], + "ipv4": "100.110.121.96", + "ipv6": "fd7a:115c:a1e0::1737:7960" + }, + "user-mon": { + "hostname": "user-mon", + "tags": [], + "ipv4": "100.103.90.82", + "ipv6": "fd7a:115c:a1e0::9e37:5a52" + }, + "user1": { + "hostname": "user1", + "tags": [], + "ipv4": "100.90.199.68", + "ipv6": "fd7a:115c:a1e0::2d01:c747" + } + } + }, + "captures": { + "exit-node": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "subnet-router": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-client": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-prod": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "tagged-server": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-kris": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user-mon": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + }, + "user1": { + "packet_filter_rules": [ + { + "SrcIPs": [ + "10.33.0.0/16", + "100.115.94.0-100.127.255.255", + "100.64.0.0-100.115.91.255", + "fd7a:115c:a1e0::/48" + ], + "DstPorts": [ + { + "IP": "*", + "Ports": { + "First": 443, + "Last": 443 + } + } + ] + } + ] + } + } +}