Skip to content

Commit 1ae40ae

Browse files
authored
[fix] : limit fw-rule description to 100 chars (#321)
* limit fw-rule description to 100 chars * address review comment
1 parent 60f8d4c commit 1ae40ae

File tree

2 files changed

+105
-4
lines changed

2 files changed

+105
-4
lines changed

cloud/linode/firewall/firewalls.go

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020

2121
const (
2222
maxFirewallRuleLabelLen = 32
23+
maxFirewallRuleDescLen = 100
2324
maxIPsPerFirewall = 255
2425
maxRulesPerFirewall = 25
2526
)
@@ -183,6 +184,16 @@ func chunkIPs(ips []string) [][]string {
183184
return chunks
184185
}
185186

187+
// truncateFWRuleDesc truncates the description to maxFirewallRuleDescLen if it exceeds the limit.
188+
func truncateFWRuleDesc(desc string) string {
189+
if len(desc) > maxFirewallRuleDescLen {
190+
newDesc := desc[0:maxFirewallRuleDescLen-3] + "..."
191+
klog.Infof("Firewall rule description '%s' is too long. Stripping it to '%s'", desc, newDesc)
192+
desc = newDesc
193+
}
194+
return desc
195+
}
196+
186197
// processACL takes the IPs, aclType, label etc and formats them into the passed linodego.FirewallCreateOptions pointer.
187198
func processACL(fwcreateOpts *linodego.FirewallCreateOptions, aclType, label, svcName, ports string, ips linodego.NetworkAddresses) error {
188199
ruleLabel := fmt.Sprintf("%s-%s", aclType, svcName)
@@ -205,10 +216,11 @@ func processACL(fwcreateOpts *linodego.FirewallCreateOptions, aclType, label, sv
205216
ipv4chunks := chunkIPs(ipv4s)
206217
for i, chunk := range ipv4chunks {
207218
v4chunk := chunk
219+
desc := fmt.Sprintf("Rule %d, Created by linode-ccm: %s, for %s", i, label, svcName)
208220
fwcreateOpts.Rules.Inbound = append(fwcreateOpts.Rules.Inbound, linodego.FirewallRule{
209221
Action: aclType,
210222
Label: ruleLabel,
211-
Description: fmt.Sprintf("Rule %d, Created by linode-ccm: %s, for %s", i, label, svcName),
223+
Description: truncateFWRuleDesc(desc),
212224
Protocol: linodego.TCP, // Nodebalancers support only TCP.
213225
Ports: ports,
214226
Addresses: linodego.NetworkAddresses{IPv4: &v4chunk},
@@ -218,20 +230,22 @@ func processACL(fwcreateOpts *linodego.FirewallCreateOptions, aclType, label, sv
218230
ipv6chunks := chunkIPs(ipv6s)
219231
for i, chunk := range ipv6chunks {
220232
v6chunk := chunk
233+
desc := fmt.Sprintf("Rule %d, Created by linode-ccm: %s, for %s", i, label, svcName)
221234
fwcreateOpts.Rules.Inbound = append(fwcreateOpts.Rules.Inbound, linodego.FirewallRule{
222235
Action: aclType,
223236
Label: ruleLabel,
224-
Description: fmt.Sprintf("Rule %d, Created by linode-ccm: %s, for %s", i, label, svcName),
237+
Description: truncateFWRuleDesc(desc),
225238
Protocol: linodego.TCP, // Nodebalancers support only TCP.
226239
Ports: ports,
227240
Addresses: linodego.NetworkAddresses{IPv6: &v6chunk},
228241
})
229242
}
230243
} else {
244+
desc := fmt.Sprintf("Created by linode-ccm: %s, for %s", label, svcName)
231245
fwcreateOpts.Rules.Inbound = append(fwcreateOpts.Rules.Inbound, linodego.FirewallRule{
232246
Action: aclType,
233247
Label: ruleLabel,
234-
Description: fmt.Sprintf("Created by linode-ccm: %s, for %s", label, svcName),
248+
Description: truncateFWRuleDesc(desc),
235249
Protocol: linodego.TCP, // Nodebalancers support only TCP.
236250
Ports: ports,
237251
Addresses: ips,
@@ -453,7 +467,7 @@ func (l *LinodeClient) updateNodeBalancerFirewallWithACL(
453467
return nil
454468
}
455469

456-
fwCreateOpts, err := CreateFirewallOptsForSvc(service.Name, []string{""}, service)
470+
fwCreateOpts, err := CreateFirewallOptsForSvc(firewalls[0].Label, []string{""}, service)
457471
if err != nil {
458472
return err
459473
}

cloud/linode/loadbalancers_test.go

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,10 @@ func TestCCMLoadBalancers(t *testing.T) {
258258
name: "Update Load Balancer - No Nodes",
259259
f: testUpdateLoadBalancerNoNodes,
260260
},
261+
{
262+
name: "Create Load Balancer - Very long Service name",
263+
f: testVeryLongServiceName,
264+
},
261265
}
262266

263267
for _, tc := range testCases {
@@ -816,6 +820,89 @@ func testUpdateLoadBalancerAddPortAnnotation(t *testing.T, client *linodego.Clie
816820
}
817821
}
818822

823+
func toJSON(v interface{}) string {
824+
data, _ := json.Marshal(v)
825+
return string(data)
826+
}
827+
828+
func testVeryLongServiceName(t *testing.T, client *linodego.Client, _ *fakeAPI) {
829+
ipv4DenyList := make([]string, 130)
830+
ipv6DenyList := make([]string, 130)
831+
832+
for i := 0; i < len(ipv4DenyList); i++ {
833+
ipv4DenyList[i] = fmt.Sprintf("192.168.1.%d/32", i)
834+
ipv6DenyList[i] = fmt.Sprintf("2001:db8::%x/128", i)
835+
}
836+
denyListJSON := fmt.Sprintf(`{
837+
"denyList": {
838+
"ipv4": %s,
839+
"ipv6": %s
840+
}
841+
}`, toJSON(ipv4DenyList), toJSON(ipv6DenyList))
842+
843+
svc := &v1.Service{
844+
ObjectMeta: metav1.ObjectMeta{
845+
Name: strings.Repeat(randString(), 6),
846+
UID: "foobar123",
847+
Annotations: map[string]string{
848+
annotations.AnnLinodeCloudFirewallACL: denyListJSON,
849+
},
850+
},
851+
Spec: v1.ServiceSpec{
852+
Ports: []v1.ServicePort{
853+
{
854+
Name: randString(),
855+
Protocol: "TCP",
856+
Port: int32(80),
857+
NodePort: int32(30000),
858+
},
859+
},
860+
},
861+
}
862+
863+
nodes := []*v1.Node{
864+
{
865+
Status: v1.NodeStatus{
866+
Addresses: []v1.NodeAddress{
867+
{
868+
Type: v1.NodeInternalIP,
869+
Address: "127.0.0.1",
870+
},
871+
},
872+
},
873+
},
874+
}
875+
876+
lb := newLoadbalancers(client, "us-west").(*loadbalancers)
877+
fakeClientset := fake.NewSimpleClientset()
878+
lb.kubeClient = fakeClientset
879+
880+
defer func() {
881+
_ = lb.EnsureLoadBalancerDeleted(context.TODO(), "linodelb", svc)
882+
}()
883+
884+
lbStatus, err := lb.EnsureLoadBalancer(context.TODO(), "linodelb", svc, nodes)
885+
if err != nil {
886+
t.Errorf("EnsureLoadBalancer returned an error: %s", err)
887+
}
888+
svc.Status.LoadBalancer = *lbStatus
889+
stubService(fakeClientset, svc)
890+
891+
svc.ObjectMeta.SetAnnotations(map[string]string{
892+
annotations.AnnLinodeCloudFirewallACL: `{
893+
"denyList": {
894+
"ipv4": ["192.168.1.0/32"],
895+
"ipv6": ["2001:db8::/128"]
896+
}
897+
}`,
898+
})
899+
900+
err = lb.UpdateLoadBalancer(context.TODO(), "linodelb", svc, nodes)
901+
if err != nil {
902+
t.Fatalf("UpdateLoadBalancer returned an error with updated annotations: %s", err)
903+
}
904+
}
905+
819906
func testUpdateLoadBalancerAddTags(t *testing.T, client *linodego.Client, _ *fakeAPI) {
820907
svc := &v1.Service{
821908
ObjectMeta: metav1.ObjectMeta{

0 commit comments

Comments
 (0)