Skip to content

Commit ba189de

Browse files
committed
Slightly improve EndpointSlice address validation
Because it used both IsValidIPv4Address and ValidateEndpointIP, EndpointSlice validation produced duplicate error messages when given an invalid IP. Fix this by calling IsValidIP first, and only doing the other checks if that one fails. Also, since no one else was using the IsValidIPv4Address and IsValidIPv6Address methods anyway, just inline them into the EndpointSlice validation, so we don't have to worry about "should they do legacy or strict validation" later.
1 parent fc4bb4f commit ba189de

File tree

4 files changed

+47
-86
lines changed

4 files changed

+47
-86
lines changed

pkg/apis/discovery/validation/validation.go

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
api "k8s.io/kubernetes/pkg/apis/core"
2929
apivalidation "k8s.io/kubernetes/pkg/apis/core/validation"
3030
"k8s.io/kubernetes/pkg/apis/discovery"
31+
netutils "k8s.io/utils/net"
3132
)
3233

3334
var (
@@ -99,11 +100,25 @@ func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.Addres
99100
// and do not get validated.
100101
switch addrType {
101102
case discovery.AddressTypeIPv4:
102-
allErrs = append(allErrs, validation.IsValidIPv4Address(addressPath.Index(i), address)...)
103-
allErrs = append(allErrs, apivalidation.ValidateEndpointIP(address, addressPath.Index(i))...)
103+
ipErrs := validation.IsValidIP(addressPath.Index(i), address)
104+
if len(ipErrs) > 0 {
105+
allErrs = append(allErrs, ipErrs...)
106+
} else {
107+
if !netutils.IsIPv4String(address) {
108+
allErrs = append(allErrs, field.Invalid(addressPath, address, "must be an IPv4 address"))
109+
}
110+
allErrs = append(allErrs, apivalidation.ValidateEndpointIP(address, addressPath.Index(i))...)
111+
}
104112
case discovery.AddressTypeIPv6:
105-
allErrs = append(allErrs, validation.IsValidIPv6Address(addressPath.Index(i), address)...)
106-
allErrs = append(allErrs, apivalidation.ValidateEndpointIP(address, addressPath.Index(i))...)
113+
ipErrs := validation.IsValidIP(addressPath.Index(i), address)
114+
if len(ipErrs) > 0 {
115+
allErrs = append(allErrs, ipErrs...)
116+
} else {
117+
if !netutils.IsIPv6String(address) {
118+
allErrs = append(allErrs, field.Invalid(addressPath, address, "must be an IPv6 address"))
119+
}
120+
allErrs = append(allErrs, apivalidation.ValidateEndpointIP(address, addressPath.Index(i))...)
121+
}
107122
case discovery.AddressTypeFQDN:
108123
allErrs = append(allErrs, validation.IsFullyQualifiedDomainName(addressPath.Index(i), address)...)
109124
}

pkg/apis/discovery/validation/validation_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ func TestValidateEndpointSlice(t *testing.T) {
408408
},
409409
},
410410
"bad-ip": {
411-
expectedErrors: 2,
411+
expectedErrors: 1,
412412
endpointSlice: &discovery.EndpointSlice{
413413
ObjectMeta: standardMeta,
414414
AddressType: discovery.AddressTypeIPv4,
@@ -423,7 +423,7 @@ func TestValidateEndpointSlice(t *testing.T) {
423423
},
424424
},
425425
"bad-ipv4": {
426-
expectedErrors: 3,
426+
expectedErrors: 2,
427427
endpointSlice: &discovery.EndpointSlice{
428428
ObjectMeta: standardMeta,
429429
AddressType: discovery.AddressTypeIPv4,
@@ -438,7 +438,7 @@ func TestValidateEndpointSlice(t *testing.T) {
438438
},
439439
},
440440
"bad-ipv6": {
441-
expectedErrors: 4,
441+
expectedErrors: 2,
442442
endpointSlice: &discovery.EndpointSlice{
443443
ObjectMeta: standardMeta,
444444
AddressType: discovery.AddressTypeIPv6,

staging/src/k8s.io/apimachinery/pkg/util/validation/ip.go

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,6 @@ func GetWarningsForIP(fldPath *field.Path, value string) []string {
6565
return nil
6666
}
6767

68-
// IsValidIPv4Address tests that the argument is a valid IPv4 address.
69-
func IsValidIPv4Address(fldPath *field.Path, value string) field.ErrorList {
70-
var allErrors field.ErrorList
71-
ip := netutils.ParseIPSloppy(value)
72-
if ip == nil || ip.To4() == nil {
73-
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IPv4 address"))
74-
}
75-
return allErrors
76-
}
77-
78-
// IsValidIPv6Address tests that the argument is a valid IPv6 address.
79-
func IsValidIPv6Address(fldPath *field.Path, value string) field.ErrorList {
80-
var allErrors field.ErrorList
81-
ip := netutils.ParseIPSloppy(value)
82-
if ip == nil || ip.To4() != nil {
83-
allErrors = append(allErrors, field.Invalid(fldPath, value, "must be a valid IPv6 address"))
84-
}
85-
return allErrors
86-
}
87-
8868
// IsValidCIDR tests that the argument is a valid CIDR value.
8969
func IsValidCIDR(fldPath *field.Path, value string) field.ErrorList {
9070
var allErrors field.ErrorList

staging/src/k8s.io/apimachinery/pkg/util/validation/ip_test.go

Lines changed: 25 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -26,70 +26,58 @@ import (
2626

2727
func TestIsValidIP(t *testing.T) {
2828
for _, tc := range []struct {
29-
name string
30-
in string
31-
family int
32-
err string
29+
name string
30+
in string
31+
err string
3332
}{
3433
// GOOD VALUES
3534
{
36-
name: "ipv4",
37-
in: "1.2.3.4",
38-
family: 4,
35+
name: "ipv4",
36+
in: "1.2.3.4",
3937
},
4038
{
41-
name: "ipv4, all zeros",
42-
in: "0.0.0.0",
43-
family: 4,
39+
name: "ipv4, all zeros",
40+
in: "0.0.0.0",
4441
},
4542
{
46-
name: "ipv4, max",
47-
in: "255.255.255.255",
48-
family: 4,
43+
name: "ipv4, max",
44+
in: "255.255.255.255",
4945
},
5046
{
51-
name: "ipv6",
52-
in: "1234::abcd",
53-
family: 6,
47+
name: "ipv6",
48+
in: "1234::abcd",
5449
},
5550
{
56-
name: "ipv6, all zeros, collapsed",
57-
in: "::",
58-
family: 6,
51+
name: "ipv6, all zeros, collapsed",
52+
in: "::",
5953
},
6054
{
61-
name: "ipv6, max",
62-
in: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
63-
family: 6,
55+
name: "ipv6, max",
56+
in: "ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff",
6457
},
6558

6659
// GOOD, THOUGH NON-CANONICAL, VALUES
6760
{
68-
name: "ipv6, all zeros, expanded (non-canonical)",
69-
in: "0:0:0:0:0:0:0:0",
70-
family: 6,
61+
name: "ipv6, all zeros, expanded (non-canonical)",
62+
in: "0:0:0:0:0:0:0:0",
7163
},
7264
{
73-
name: "ipv6, leading 0s (non-canonical)",
74-
in: "0001:002:03:4::",
75-
family: 6,
65+
name: "ipv6, leading 0s (non-canonical)",
66+
in: "0001:002:03:4::",
7667
},
7768
{
78-
name: "ipv6, capital letters (non-canonical)",
79-
in: "1234::ABCD",
80-
family: 6,
69+
name: "ipv6, capital letters (non-canonical)",
70+
in: "1234::ABCD",
8171
},
8272

8373
// BAD VALUES WE CURRENTLY CONSIDER GOOD
8474
{
85-
name: "ipv4 with leading 0s",
86-
in: "1.1.1.01",
87-
family: 4,
75+
name: "ipv4 with leading 0s",
76+
in: "1.1.1.01",
8877
},
8978
{
90-
name: "ipv4-in-ipv6 value",
91-
in: "::ffff:1.1.1.1",
92-
family: 4,
79+
name: "ipv4-in-ipv6 value",
80+
in: "::ffff:1.1.1.1",
9381
},
9482

9583
// BAD VALUES
@@ -172,28 +160,6 @@ func TestIsValidIP(t *testing.T) {
172160
t.Errorf("expected error for %q to contain %q but got: %q", tc.in, tc.err, errs[0].Detail)
173161
}
174162
}
175-
176-
errs = IsValidIPv4Address(field.NewPath(""), tc.in)
177-
if tc.family == 4 {
178-
if len(errs) != 0 {
179-
t.Errorf("expected %q to pass IsValidIPv4Address but got: %v", tc.in, errs)
180-
}
181-
} else {
182-
if len(errs) == 0 {
183-
t.Errorf("expected %q to fail IsValidIPv4Address", tc.in)
184-
}
185-
}
186-
187-
errs = IsValidIPv6Address(field.NewPath(""), tc.in)
188-
if tc.family == 6 {
189-
if len(errs) != 0 {
190-
t.Errorf("expected %q to pass IsValidIPv6Address but got: %v", tc.in, errs)
191-
}
192-
} else {
193-
if len(errs) == 0 {
194-
t.Errorf("expected %q to fail IsValidIPv6Address", tc.in)
195-
}
196-
}
197163
})
198164
}
199165
}

0 commit comments

Comments
 (0)