@@ -839,6 +839,272 @@ func Test_NetworksNetMapGenShouldExcludeOtherRouters(t *testing.T) {
839839 assert .Len (t , sourcePeers , 2 , "expected source peers don't match" )
840840}
841841
842+ func Test_ExpandPortsAndRanges_SSHRuleExpansion (t * testing.T ) {
843+ tests := []struct {
844+ name string
845+ peer * nbpeer.Peer
846+ rule * PolicyRule
847+ base FirewallRule
848+ expectedPorts []string
849+ }{
850+ {
851+ name : "adds port 22022 when SSH enabled on modern peer with port 22" ,
852+ peer : & nbpeer.Peer {
853+ ID : "peer1" ,
854+ SSHEnabled : true ,
855+ Meta : nbpeer.PeerSystemMeta {
856+ WtVersion : "0.60.0" ,
857+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
858+ },
859+ },
860+ rule : & PolicyRule {
861+ Protocol : PolicyRuleProtocolTCP ,
862+ Ports : []string {"22" },
863+ },
864+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
865+ expectedPorts : []string {"22" , "22022" },
866+ },
867+ {
868+ name : "adds port 22022 once when port 22 is duplicated within policy" ,
869+ peer : & nbpeer.Peer {
870+ ID : "peer1" ,
871+ SSHEnabled : true ,
872+ Meta : nbpeer.PeerSystemMeta {
873+ WtVersion : "0.60.0" ,
874+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
875+ },
876+ },
877+ rule : & PolicyRule {
878+ Protocol : PolicyRuleProtocolTCP ,
879+ Ports : []string {"22" , "80" , "22" },
880+ },
881+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
882+ expectedPorts : []string {"22" , "80" , "22" , "22022" },
883+ },
884+ {
885+ name : "does not add 22022 for peer with old version" ,
886+ peer : & nbpeer.Peer {
887+ ID : "peer1" ,
888+ SSHEnabled : true ,
889+ Meta : nbpeer.PeerSystemMeta {
890+ WtVersion : "0.59.0" ,
891+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
892+ },
893+ },
894+ rule : & PolicyRule {
895+ Protocol : PolicyRuleProtocolTCP ,
896+ Ports : []string {"22" },
897+ },
898+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
899+ expectedPorts : []string {"22" },
900+ },
901+ {
902+ name : "does not add 22022 when SSHEnabled is false" ,
903+ peer : & nbpeer.Peer {
904+ ID : "peer1" ,
905+ SSHEnabled : false ,
906+ Meta : nbpeer.PeerSystemMeta {
907+ WtVersion : "0.60.0" ,
908+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
909+ },
910+ },
911+ rule : & PolicyRule {
912+ Protocol : PolicyRuleProtocolTCP ,
913+ Ports : []string {"22" },
914+ },
915+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
916+ expectedPorts : []string {"22" },
917+ },
918+ {
919+ name : "does not add 22022 when ServerSSHAllowed is false" ,
920+ peer : & nbpeer.Peer {
921+ ID : "peer1" ,
922+ SSHEnabled : true ,
923+ Meta : nbpeer.PeerSystemMeta {
924+ WtVersion : "0.60.0" ,
925+ Flags : nbpeer.Flags {ServerSSHAllowed : false },
926+ },
927+ },
928+ rule : & PolicyRule {
929+ Protocol : PolicyRuleProtocolTCP ,
930+ Ports : []string {"22" },
931+ },
932+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
933+ expectedPorts : []string {"22" },
934+ },
935+ {
936+ name : "does not add 22022 for UDP protocol" ,
937+ peer : & nbpeer.Peer {
938+ ID : "peer1" ,
939+ SSHEnabled : true ,
940+ Meta : nbpeer.PeerSystemMeta {
941+ WtVersion : "0.60.0" ,
942+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
943+ },
944+ },
945+ rule : & PolicyRule {
946+ Protocol : PolicyRuleProtocolUDP ,
947+ Ports : []string {"22" },
948+ },
949+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "udp" },
950+ expectedPorts : []string {"22" },
951+ },
952+ {
953+ name : "does not add 22022 when port 22 not in rule" ,
954+ peer : & nbpeer.Peer {
955+ ID : "peer1" ,
956+ SSHEnabled : true ,
957+ Meta : nbpeer.PeerSystemMeta {
958+ WtVersion : "0.60.0" ,
959+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
960+ },
961+ },
962+ rule : & PolicyRule {
963+ Protocol : PolicyRuleProtocolTCP ,
964+ Ports : []string {"80" , "443" },
965+ },
966+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
967+ expectedPorts : []string {"80" , "443" },
968+ },
969+ {
970+ name : "does not duplicate 22022 when already present" ,
971+ peer : & nbpeer.Peer {
972+ ID : "peer1" ,
973+ SSHEnabled : true ,
974+ Meta : nbpeer.PeerSystemMeta {
975+ WtVersion : "0.60.0" ,
976+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
977+ },
978+ },
979+ rule : & PolicyRule {
980+ Protocol : PolicyRuleProtocolTCP ,
981+ Ports : []string {"22" , "22022" },
982+ },
983+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
984+ expectedPorts : []string {"22" , "22022" },
985+ },
986+ {
987+ name : "does not duplicate 22022 when already within a port range" ,
988+ peer : & nbpeer.Peer {
989+ ID : "peer1" ,
990+ SSHEnabled : true ,
991+ Meta : nbpeer.PeerSystemMeta {
992+ WtVersion : "0.60.0" ,
993+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
994+ },
995+ },
996+ rule : & PolicyRule {
997+ Protocol : PolicyRuleProtocolTCP ,
998+ PortRanges : []RulePortRange {{Start : 20 , End : 32000 }},
999+ },
1000+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1001+ expectedPorts : []string {"20-32000" },
1002+ },
1003+ {
1004+ name : "adds 22022 when port 22 in port range" ,
1005+ peer : & nbpeer.Peer {
1006+ ID : "peer1" ,
1007+ SSHEnabled : true ,
1008+ Meta : nbpeer.PeerSystemMeta {
1009+ WtVersion : "0.60.0" ,
1010+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
1011+ },
1012+ },
1013+ rule : & PolicyRule {
1014+ Protocol : PolicyRuleProtocolTCP ,
1015+ PortRanges : []RulePortRange {{Start : 20 , End : 25 }},
1016+ },
1017+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1018+ expectedPorts : []string {"20-25" , "22022" },
1019+ },
1020+ {
1021+ name : "adds single 22022 once when port 22 in multiple port ranges" ,
1022+ peer : & nbpeer.Peer {
1023+ ID : "peer1" ,
1024+ SSHEnabled : true ,
1025+ Meta : nbpeer.PeerSystemMeta {
1026+ WtVersion : "0.60.0" ,
1027+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
1028+ },
1029+ },
1030+ rule : & PolicyRule {
1031+ Protocol : PolicyRuleProtocolTCP ,
1032+ PortRanges : []RulePortRange {{Start : 20 , End : 25 }, {Start : 10 , End : 100 }},
1033+ },
1034+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1035+ expectedPorts : []string {"20-25" , "10-100" , "22022" },
1036+ },
1037+ {
1038+ name : "dev suffix version supports all features" ,
1039+ peer : & nbpeer.Peer {
1040+ ID : "peer1" ,
1041+ SSHEnabled : true ,
1042+ Meta : nbpeer.PeerSystemMeta {
1043+ WtVersion : "0.50.0-dev" ,
1044+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
1045+ },
1046+ },
1047+ rule : & PolicyRule {
1048+ Protocol : PolicyRuleProtocolTCP ,
1049+ Ports : []string {"22" },
1050+ },
1051+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1052+ expectedPorts : []string {"22" , "22022" },
1053+ },
1054+ {
1055+ name : "dev suffix version supports all features" ,
1056+ peer : & nbpeer.Peer {
1057+ ID : "peer1" ,
1058+ SSHEnabled : true ,
1059+ Meta : nbpeer.PeerSystemMeta {
1060+ WtVersion : "dev" ,
1061+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
1062+ },
1063+ },
1064+ rule : & PolicyRule {
1065+ Protocol : PolicyRuleProtocolTCP ,
1066+ Ports : []string {"22" },
1067+ },
1068+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1069+ expectedPorts : []string {"22" , "22022" },
1070+ },
1071+ {
1072+ name : "development suffix version supports all features" ,
1073+ peer : & nbpeer.Peer {
1074+ ID : "peer1" ,
1075+ SSHEnabled : true ,
1076+ Meta : nbpeer.PeerSystemMeta {
1077+ WtVersion : "development" ,
1078+ Flags : nbpeer.Flags {ServerSSHAllowed : true },
1079+ },
1080+ },
1081+ rule : & PolicyRule {
1082+ Protocol : PolicyRuleProtocolTCP ,
1083+ Ports : []string {"22" },
1084+ },
1085+ base : FirewallRule {PeerIP : "10.0.0.1" , Direction : 0 , Action : "accept" , Protocol : "tcp" },
1086+ expectedPorts : []string {"22" , "22022" },
1087+ },
1088+ }
1089+
1090+ for _ , tt := range tests {
1091+ t .Run (tt .name , func (t * testing.T ) {
1092+ result := expandPortsAndRanges (tt .base , tt .rule , tt .peer )
1093+
1094+ var ports []string
1095+ for _ , fr := range result {
1096+ if fr .Port != "" {
1097+ ports = append (ports , fr .Port )
1098+ } else if fr .PortRange .Start > 0 {
1099+ ports = append (ports , fmt .Sprintf ("%d-%d" , fr .PortRange .Start , fr .PortRange .End ))
1100+ }
1101+ }
1102+
1103+ assert .Equal (t , tt .expectedPorts , ports , "expanded ports should match expected" )
1104+ })
1105+ }
1106+ }
1107+
8421108func Test_FilterZoneRecordsForPeers (t * testing.T ) {
8431109 tests := []struct {
8441110 name string
0 commit comments