From 2f2be32a513f9e2e878553672189d24d098205bc Mon Sep 17 00:00:00 2001 From: phm07 <22707808+phm07@users.noreply.github.com> Date: Fri, 10 May 2024 10:17:43 +0200 Subject: [PATCH] fix(firewall): 'create --rules-file' not working with outbound rules (#752) This PR fixes the behavior of the `--rules-file` flag when creating firewalls. Destination IPs were not parsed correctly which lead to the request failing when an outbound rule was specified. This was fixed and tests for outbound rules were added. Closes #750 --- internal/cmd/firewall/create.go | 19 ++++++++++++++----- internal/cmd/firewall/create_test.go | 14 ++++++++++++++ internal/cmd/firewall/replace_rules_test.go | 14 ++++++++++++++ internal/cmd/firewall/testdata/rules.json | 11 +++++++++++ 4 files changed, 53 insertions(+), 5 deletions(-) diff --git a/internal/cmd/firewall/create.go b/internal/cmd/firewall/create.go index 4aaf7088..4137ae4b 100644 --- a/internal/cmd/firewall/create.go +++ b/internal/cmd/firewall/create.go @@ -67,12 +67,21 @@ var CreateCmd = base.CreateCmd{ } sourceNets = append(sourceNets, *sourceNet) } + var destNets []net.IPNet + for i, destIP := range rule.DestinationIPs { + _, destNet, err := net.ParseCIDR(destIP) + if err != nil { + return nil, nil, fmt.Errorf("invalid CIDR on index %d : %s", i, err) + } + destNets = append(destNets, *destNet) + } opts.Rules = append(opts.Rules, hcloud.FirewallRule{ - Direction: hcloud.FirewallRuleDirection(rule.Direction), - SourceIPs: sourceNets, - Protocol: hcloud.FirewallRuleProtocol(rule.Protocol), - Port: rule.Port, - Description: rule.Description, + Direction: hcloud.FirewallRuleDirection(rule.Direction), + SourceIPs: sourceNets, + DestinationIPs: destNets, + Protocol: hcloud.FirewallRuleProtocol(rule.Protocol), + Port: rule.Port, + Description: rule.Description, }) } } diff --git a/internal/cmd/firewall/create_test.go b/internal/cmd/firewall/create_test.go index 24072e2a..28dded1f 100644 --- a/internal/cmd/firewall/create_test.go +++ b/internal/cmd/firewall/create_test.go @@ -58,6 +58,20 @@ func TestCreate(t *testing.T) { Port: hcloud.Ptr("443"), Description: hcloud.Ptr("Allow port 443"), }, + { + Direction: hcloud.FirewallRuleDirectionOut, + SourceIPs: nil, + DestinationIPs: []net.IPNet{ + {IP: net.IP{28, 239, 13, 1}, Mask: net.IPMask{255, 255, 255, 255}}, + {IP: net.IP{28, 239, 14, 0}, Mask: net.IPMask{255, 255, 255, 0}}, + { + IP: net.IP{0xff, 0x21, 0x1e, 0xac, 0x9a, 0x3b, 0xee, 0x58, 0x05, 0xca, 0x99, 0x0c, 0x8b, 0xc9, 0xc0, 0x3b}, + Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + }, + }, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("80"), + }, }, }). Return(hcloud.FirewallCreateResult{ diff --git a/internal/cmd/firewall/replace_rules_test.go b/internal/cmd/firewall/replace_rules_test.go index e5e1fec9..ed4c6264 100644 --- a/internal/cmd/firewall/replace_rules_test.go +++ b/internal/cmd/firewall/replace_rules_test.go @@ -59,6 +59,20 @@ func TestReplaceRules(t *testing.T) { Port: hcloud.Ptr("443"), Description: hcloud.Ptr("Allow port 443"), }, + { + Direction: hcloud.FirewallRuleDirectionOut, + SourceIPs: nil, + DestinationIPs: []net.IPNet{ + {IP: net.IP{28, 239, 13, 1}, Mask: net.IPMask{255, 255, 255, 255}}, + {IP: net.IP{28, 239, 14, 0}, Mask: net.IPMask{255, 255, 255, 0}}, + { + IP: net.IP{0xff, 0x21, 0x1e, 0xac, 0x9a, 0x3b, 0xee, 0x58, 0x05, 0xca, 0x99, 0x0c, 0x8b, 0xc9, 0xc0, 0x3b}, + Mask: net.IPMask{255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}, + }, + }, + Protocol: hcloud.FirewallRuleProtocolTCP, + Port: hcloud.Ptr("80"), + }, }, }). Return([]*hcloud.Action{{ID: 123}, {ID: 321}}, nil, nil) diff --git a/internal/cmd/firewall/testdata/rules.json b/internal/cmd/firewall/testdata/rules.json index 7efec894..3b9e3829 100644 --- a/internal/cmd/firewall/testdata/rules.json +++ b/internal/cmd/firewall/testdata/rules.json @@ -19,5 +19,16 @@ "0.0.0.0/0", "::/0" ] + }, + { + "direction": "out", + "source_ips": [], + "destination_ips": [ + "28.239.13.1/32", + "28.239.14.0/24", + "ff21:1eac:9a3b:ee58:5ca:990c:8bc9:c03b/128" + ], + "protocol": "tcp", + "port": "80" } ]