Skip to content

Commit 5fb0239

Browse files
fasaxctomdee
authored andcommitted
Add validation for backend Rules.
Defend against ports with no protocol. (cherry picked from commit a975979)
1 parent 40b5d95 commit 5fb0239

File tree

2 files changed

+57
-2
lines changed

2 files changed

+57
-2
lines changed

lib/validator/validator.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
1+
// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved.
22

33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ import (
2727
"github.com/projectcalico/libcalico-go/lib/selector"
2828
"github.com/projectcalico/libcalico-go/lib/selector/tokenizer"
2929

30+
"github.com/projectcalico/libcalico-go/lib/backend/model"
3031
"gopkg.in/go-playground/validator.v8"
3132
)
3233

@@ -92,6 +93,7 @@ func init() {
9293
registerStructValidator(validateIPPool, api.IPPool{})
9394
registerStructValidator(validateICMPFields, api.ICMPFields{})
9495
registerStructValidator(validateRule, api.Rule{})
96+
registerStructValidator(validateBackendRule, model.Rule{})
9597
registerStructValidator(validateNodeSpec, api.NodeSpec{})
9698
}
9799

@@ -364,6 +366,32 @@ func validateRule(v *validator.Validate, structLevel *validator.StructLevel) {
364366
}
365367
}
366368

369+
func validateBackendRule(v *validator.Validate, structLevel *validator.StructLevel) {
370+
rule := structLevel.CurrentStruct.Interface().(model.Rule)
371+
372+
// If the protocol is neither tcp (6) nor udp (17) check that the port values have not
373+
// been specified.
374+
if rule.Protocol == nil || !rule.Protocol.SupportsPorts() {
375+
if len(rule.SrcPorts) > 0 {
376+
structLevel.ReportError(reflect.ValueOf(rule.SrcPorts),
377+
"SrcPorts", "", reason("protocol does not support ports"))
378+
}
379+
if len(rule.NotSrcPorts) > 0 {
380+
structLevel.ReportError(reflect.ValueOf(rule.NotSrcPorts),
381+
"NotSrcPorts", "", reason("protocol does not support ports"))
382+
}
383+
384+
if len(rule.DstPorts) > 0 {
385+
structLevel.ReportError(reflect.ValueOf(rule.DstPorts),
386+
"DstPorts", "", reason("protocol does not support ports"))
387+
}
388+
if len(rule.NotDstPorts) > 0 {
389+
structLevel.ReportError(reflect.ValueOf(rule.NotDstPorts),
390+
"NotDstPorts", "", reason("protocol does not support ports"))
391+
}
392+
}
393+
}
394+
367395
func validateNodeSpec(v *validator.Validate, structLevel *validator.StructLevel) {
368396
ns := structLevel.CurrentStruct.Interface().(api.NodeSpec)
369397

lib/validator/validator_test.go

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// Copyright (c) 2016 Tigera, Inc. All rights reserved.
1+
// Copyright (c) 2016-2017 Tigera, Inc. All rights reserved.
22

33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
@@ -52,6 +52,8 @@ func init() {
5252
netv6_3 := testutils.MustParseNetwork("aabb:aabb::ffff/122")
5353
netv6_4 := testutils.MustParseNetwork("aabb:aabb::ffff/10")
5454

55+
protoTCP := numorstring.ProtocolFromString("tcp")
56+
5557
// Perform basic validation of different fields and structures to test simple valid/invalid
5658
// scenarios. This does not test precise error strings - but does cover a lot of the validation
5759
// code paths.
@@ -88,6 +90,24 @@ func init() {
8890
Entry("should accept IP version 6 (m)", model.Rule{IPVersion: &V6}, true),
8991
Entry("should reject IP version 0 (m)", model.Rule{IPVersion: &V0}, false),
9092

93+
// (Backend model) Ports.
94+
Entry("should accept ports with tcp protocol (m)", model.Rule{
95+
Protocol: &protoTCP,
96+
SrcPorts: []numorstring.Port{numorstring.SinglePort(80)},
97+
}, true),
98+
Entry("should reject src ports with no protocol (m)", model.Rule{
99+
SrcPorts: []numorstring.Port{numorstring.SinglePort(80)},
100+
}, false),
101+
Entry("should reject dst ports with no protocol (m)", model.Rule{
102+
DstPorts: []numorstring.Port{numorstring.SinglePort(80)},
103+
}, false),
104+
Entry("should reject !src ports with no protocol (m)", model.Rule{
105+
NotSrcPorts: []numorstring.Port{numorstring.SinglePort(80)},
106+
}, false),
107+
Entry("should reject !dst ports with no protocol (m)", model.Rule{
108+
NotDstPorts: []numorstring.Port{numorstring.SinglePort(80)},
109+
}, false),
110+
91111
// (API) IP version.
92112
Entry("should accept IP version 4", api.Rule{Action: "allow", IPVersion: &V4}, true),
93113
Entry("should accept IP version 6", api.Rule{Action: "allow", IPVersion: &V6}, true),
@@ -350,6 +370,13 @@ func init() {
350370
Ports: []numorstring.Port{numorstring.SinglePort(1)},
351371
},
352372
}, true),
373+
Entry("should reject Rule with dest ports and no protocol",
374+
api.Rule{
375+
Action: "allow",
376+
Destination: api.EntityRule{
377+
Ports: []numorstring.Port{numorstring.SinglePort(1)},
378+
},
379+
}, false),
353380
Entry("should reject Rule with invalid port (port 0)",
354381
api.Rule{
355382
Action: "allow",

0 commit comments

Comments
 (0)