From 1c31f04faba8fe3279839c975d793aacca51fbc0 Mon Sep 17 00:00:00 2001 From: Kristoffer Dalby Date: Mon, 23 Feb 2026 04:23:17 +0100 Subject: [PATCH] hscontrol/policy/v2: add TestACLToGrants Add test for aclToGrants() function that converts ACL rules to Grant format. Tests conversion of: - Single-port TCP rules - Multiple ACL entries to multiple Grants - Port ranges and multiple ports in a single rule - Wildcard protocols - UDP, ICMP, and other protocol types Ensures backward compatibility by verifying that ACL rules are correctly transformed to the new Grant format. Updates #2180 --- hscontrol/policy/v2/types_test.go | 163 ++++++++++++++++++++++++++++++ 1 file changed, 163 insertions(+) diff --git a/hscontrol/policy/v2/types_test.go b/hscontrol/policy/v2/types_test.go index 24b1c260..ad1b53be 100644 --- a/hscontrol/policy/v2/types_test.go +++ b/hscontrol/policy/v2/types_test.go @@ -4748,3 +4748,166 @@ func TestUnmarshalGrants(t *testing.T) { }) } } + +func TestACLToGrants(t *testing.T) { + tests := []struct { + name string + acl ACL + want []Grant + }{ + { + name: "single-destination-tcp", + acl: ACL{ + Action: ActionAccept, + Protocol: ProtocolNameTCP, + Sources: Aliases{gp("group:eng")}, + Destinations: []AliasWithPorts{ + { + Alias: tp("tag:server"), + Ports: []tailcfg.PortRange{{First: 443, Last: 443}}, + }, + }, + }, + want: []Grant{ + { + Sources: Aliases{gp("group:eng")}, + Destinations: Aliases{tp("tag:server")}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameTCP, + Ports: []tailcfg.PortRange{{First: 443, Last: 443}}, + }, + }, + }, + }, + }, + { + name: "multiple-destinations-creates-multiple-grants", + acl: ACL{ + Action: ActionAccept, + Protocol: ProtocolNameTCP, + Sources: Aliases{gp("group:eng")}, + Destinations: []AliasWithPorts{ + { + Alias: tp("tag:web"), + Ports: []tailcfg.PortRange{{First: 80, Last: 80}}, + }, + { + Alias: tp("tag:db"), + Ports: []tailcfg.PortRange{{First: 5432, Last: 5432}}, + }, + }, + }, + want: []Grant{ + { + Sources: Aliases{gp("group:eng")}, + Destinations: Aliases{tp("tag:web")}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameTCP, + Ports: []tailcfg.PortRange{{First: 80, Last: 80}}, + }, + }, + }, + { + Sources: Aliases{gp("group:eng")}, + Destinations: Aliases{tp("tag:db")}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameTCP, + Ports: []tailcfg.PortRange{{First: 5432, Last: 5432}}, + }, + }, + }, + }, + }, + { + name: "wildcard-protocol", + acl: ACL{ + Action: ActionAccept, + Protocol: ProtocolNameWildcard, + Sources: Aliases{gp("group:admin")}, + Destinations: []AliasWithPorts{ + { + Alias: up("alice@example.com"), + Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, + }, + }, + }, + want: []Grant{ + { + Sources: Aliases{gp("group:admin")}, + Destinations: Aliases{up("alice@example.com")}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameWildcard, + Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, + }, + }, + }, + }, + }, + { + name: "udp-with-port-range", + acl: ACL{ + Action: ActionAccept, + Protocol: ProtocolNameUDP, + Sources: Aliases{up("bob@example.com")}, + Destinations: []AliasWithPorts{ + { + Alias: tp("tag:voip"), + Ports: []tailcfg.PortRange{{First: 10000, Last: 20000}}, + }, + }, + }, + want: []Grant{ + { + Sources: Aliases{up("bob@example.com")}, + Destinations: Aliases{tp("tag:voip")}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameUDP, + Ports: []tailcfg.PortRange{{First: 10000, Last: 20000}}, + }, + }, + }, + }, + }, + { + name: "icmp-protocol", + acl: ACL{ + Action: ActionAccept, + Protocol: ProtocolNameICMP, + Sources: Aliases{gp("group:monitoring")}, + Destinations: []AliasWithPorts{ + { + Alias: new(Asterix), + Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, + }, + }, + }, + want: []Grant{ + { + Sources: Aliases{gp("group:monitoring")}, + Destinations: Aliases{new(Asterix)}, + InternetProtocols: []ProtocolPort{ + { + Protocol: ProtocolNameICMP, + Ports: []tailcfg.PortRange{tailcfg.PortRangeAny}, + }, + }, + }, + }, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := aclToGrants(tt.acl) + + if diff := cmp.Diff(tt.want, got); diff != "" { + t.Errorf("aclToGrants() mismatch (-want +got):\n%s", diff) + } + }) + } +}