backport from: https://github.com/kubernetes/kubernetes/pull/100315 https://github.com/kubernetes/kubernetes/pull/101386 Signed-off-by: leizhongkai <leizhongkai@huawei.com>
210 lines
7.5 KiB
Diff
210 lines
7.5 KiB
Diff
From 9d22c94b7171a9a6ce0d167f6cb25abce2079941 Mon Sep 17 00:00:00 2001
|
|
From: Rob Scott <robertjscott@google.com>
|
|
Date: Fri, 9 Apr 2021 15:24:17 -0700
|
|
Subject: [PATCH] Updating EndpointSlice validation to match Endpoints
|
|
validation
|
|
|
|
(cherry picked from commit dd95bba6cd1dfec0985d3e1068c12713597cbe4a)
|
|
---
|
|
pkg/apis/core/validation/validation.go | 18 +++++----
|
|
pkg/apis/core/validation/validation_test.go | 40 +++++++++++++++++++
|
|
pkg/apis/discovery/validation/validation.go | 2 +
|
|
pkg/apis/discovery/validation/validation_test.go | 51 ++++++++++++++++++++++--
|
|
4 files changed, 101 insertions(+), 10 deletions(-)
|
|
|
|
diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go
|
|
index af58e0e..d5e9037 100644
|
|
--- a/pkg/apis/core/validation/validation.go
|
|
+++ b/pkg/apis/core/validation/validation.go
|
|
@@ -4238,7 +4238,7 @@ func ValidateService(service *core.Service) field.ErrorList {
|
|
allErrs = append(allErrs, field.Invalid(idxPath, ip, msgs[i]))
|
|
}
|
|
} else {
|
|
- allErrs = append(allErrs, validateNonSpecialIP(ip, idxPath)...)
|
|
+ allErrs = append(allErrs, ValidateNonSpecialIP(ip, idxPath)...)
|
|
}
|
|
}
|
|
|
|
@@ -5673,15 +5673,19 @@ func validateEndpointAddress(address *core.EndpointAddress, fldPath *field.Path)
|
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("nodeName"), *address.NodeName, msg))
|
|
}
|
|
}
|
|
- allErrs = append(allErrs, validateNonSpecialIP(address.IP, fldPath.Child("ip"))...)
|
|
+ allErrs = append(allErrs, ValidateNonSpecialIP(address.IP, fldPath.Child("ip"))...)
|
|
return allErrs
|
|
}
|
|
|
|
-func validateNonSpecialIP(ipAddress string, fldPath *field.Path) field.ErrorList {
|
|
- // We disallow some IPs as endpoints or external-ips. Specifically,
|
|
- // unspecified and loopback addresses are nonsensical and link-local
|
|
- // addresses tend to be used for node-centric purposes (e.g. metadata
|
|
- // service).
|
|
+// ValidateNonSpecialIP is used to validate Endpoints, EndpointSlices, and
|
|
+// external IPs. Specifically, this disallows unspecified and loopback addresses
|
|
+// are nonsensical and link-local addresses tend to be used for node-centric
|
|
+// purposes (e.g. metadata service).
|
|
+//
|
|
+// IPv6 references
|
|
+// - https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
|
|
+// - https://www.iana.org/assignments/ipv6-multicast-addresses/ipv6-multicast-addresses.xhtml
|
|
+func ValidateNonSpecialIP(ipAddress string, fldPath *field.Path) field.ErrorList {
|
|
allErrs := field.ErrorList{}
|
|
ip := net.ParseIP(ipAddress)
|
|
if ip == nil {
|
|
diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go
|
|
index bfdb523..f379cd4 100644
|
|
--- a/pkg/apis/core/validation/validation_test.go
|
|
+++ b/pkg/apis/core/validation/validation_test.go
|
|
@@ -16915,3 +16915,43 @@ func TestValidatePodTemplateSpecSeccomp(t *testing.T) {
|
|
asserttestify.Equal(t, test.expectedErr, err, "TestCase[%d]: %s", i, test.description)
|
|
}
|
|
}
|
|
+
|
|
+func TestValidateNonSpecialIP(t *testing.T) {
|
|
+ fp := field.NewPath("ip")
|
|
+
|
|
+ // Valid values.
|
|
+ for _, tc := range []struct {
|
|
+ desc string
|
|
+ ip string
|
|
+ }{
|
|
+ {"ipv4", "10.1.2.3"},
|
|
+ {"ipv6", "2000::1"},
|
|
+ } {
|
|
+ t.Run(tc.desc, func(t *testing.T) {
|
|
+ errs := ValidateNonSpecialIP(tc.ip, fp)
|
|
+ if len(errs) != 0 {
|
|
+ t.Errorf("ValidateNonSpecialIP(%q, ...) = %v; want nil", tc.ip, errs)
|
|
+ }
|
|
+ })
|
|
+ }
|
|
+ // Invalid cases
|
|
+ for _, tc := range []struct {
|
|
+ desc string
|
|
+ ip string
|
|
+ }{
|
|
+ {"ipv4 unspecified", "0.0.0.0"},
|
|
+ {"ipv6 unspecified", "::0"},
|
|
+ {"ipv4 localhost", "127.0.0.0"},
|
|
+ {"ipv4 localhost", "127.255.255.255"},
|
|
+ {"ipv6 localhost", "::1"},
|
|
+ {"ipv6 link local", "fe80::"},
|
|
+ {"ipv6 local multicast", "ff02::"},
|
|
+ } {
|
|
+ t.Run(tc.desc, func(t *testing.T) {
|
|
+ errs := ValidateNonSpecialIP(tc.ip, fp)
|
|
+ if len(errs) == 0 {
|
|
+ t.Errorf("ValidateNonSpecialIP(%q, ...) = nil; want non-nil (errors)", tc.ip)
|
|
+ }
|
|
+ })
|
|
+ }
|
|
+}
|
|
diff --git a/pkg/apis/discovery/validation/validation.go b/pkg/apis/discovery/validation/validation.go
|
|
index 8499e7a..d1fa4c8 100644
|
|
--- a/pkg/apis/discovery/validation/validation.go
|
|
+++ b/pkg/apis/discovery/validation/validation.go
|
|
@@ -96,8 +96,10 @@ func validateEndpoints(endpoints []discovery.Endpoint, addrType discovery.Addres
|
|
switch addrType {
|
|
case discovery.AddressTypeIPv4:
|
|
allErrs = append(allErrs, validation.IsValidIPv4Address(addressPath.Index(i), address)...)
|
|
+ allErrs = append(allErrs, apivalidation.ValidateNonSpecialIP(address, addressPath.Index(i))...)
|
|
case discovery.AddressTypeIPv6:
|
|
allErrs = append(allErrs, validation.IsValidIPv6Address(addressPath.Index(i), address)...)
|
|
+ allErrs = append(allErrs, apivalidation.ValidateNonSpecialIP(address, addressPath.Index(i))...)
|
|
case discovery.AddressTypeFQDN:
|
|
allErrs = append(allErrs, validation.IsFullyQualifiedDomainName(addressPath.Index(i), address)...)
|
|
}
|
|
diff --git a/pkg/apis/discovery/validation/validation_test.go b/pkg/apis/discovery/validation/validation_test.go
|
|
index 5c7d478..0d944b5 100644
|
|
--- a/pkg/apis/discovery/validation/validation_test.go
|
|
+++ b/pkg/apis/discovery/validation/validation_test.go
|
|
@@ -52,6 +52,21 @@ func TestValidateEndpointSlice(t *testing.T) {
|
|
}},
|
|
},
|
|
},
|
|
+ "good-ipv6": {
|
|
+ expectedErrors: 0,
|
|
+ endpointSlice: &discovery.EndpointSlice{
|
|
+ ObjectMeta: standardMeta,
|
|
+ AddressType: discovery.AddressTypeIPv6,
|
|
+ Ports: []discovery.EndpointPort{{
|
|
+ Name: utilpointer.StringPtr("http"),
|
|
+ Protocol: protocolPtr(api.ProtocolTCP),
|
|
+ }},
|
|
+ Endpoints: []discovery.Endpoint{{
|
|
+ Addresses: []string{"a00:100::4"},
|
|
+ Hostname: utilpointer.StringPtr("valid-123"),
|
|
+ }},
|
|
+ },
|
|
+ },
|
|
"good-fqdns": {
|
|
expectedErrors: 0,
|
|
endpointSlice: &discovery.EndpointSlice{
|
|
@@ -375,7 +390,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
|
},
|
|
},
|
|
"bad-ip": {
|
|
- expectedErrors: 1,
|
|
+ expectedErrors: 2,
|
|
endpointSlice: &discovery.EndpointSlice{
|
|
ObjectMeta: standardMeta,
|
|
AddressType: discovery.AddressTypeIPv4,
|
|
@@ -390,7 +405,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
|
},
|
|
},
|
|
"bad-ipv4": {
|
|
- expectedErrors: 2,
|
|
+ expectedErrors: 3,
|
|
endpointSlice: &discovery.EndpointSlice{
|
|
ObjectMeta: standardMeta,
|
|
AddressType: discovery.AddressTypeIPv4,
|
|
@@ -405,7 +420,7 @@ func TestValidateEndpointSlice(t *testing.T) {
|
|
},
|
|
},
|
|
"bad-ipv6": {
|
|
- expectedErrors: 2,
|
|
+ expectedErrors: 4,
|
|
endpointSlice: &discovery.EndpointSlice{
|
|
ObjectMeta: standardMeta,
|
|
AddressType: discovery.AddressTypeIPv6,
|
|
@@ -454,6 +469,36 @@ func TestValidateEndpointSlice(t *testing.T) {
|
|
expectedErrors: 3,
|
|
endpointSlice: &discovery.EndpointSlice{},
|
|
},
|
|
+ "special-ipv4": {
|
|
+ expectedErrors: 1,
|
|
+ endpointSlice: &discovery.EndpointSlice{
|
|
+ ObjectMeta: standardMeta,
|
|
+ AddressType: discovery.AddressTypeIPv4,
|
|
+ Ports: []discovery.EndpointPort{{
|
|
+ Name: utilpointer.StringPtr("http"),
|
|
+ Protocol: protocolPtr(api.ProtocolTCP),
|
|
+ }},
|
|
+ Endpoints: []discovery.Endpoint{{
|
|
+ Addresses: []string{"127.0.0.1"},
|
|
+ Hostname: utilpointer.StringPtr("valid-123"),
|
|
+ }},
|
|
+ },
|
|
+ },
|
|
+ "special-ipv6": {
|
|
+ expectedErrors: 1,
|
|
+ endpointSlice: &discovery.EndpointSlice{
|
|
+ ObjectMeta: standardMeta,
|
|
+ AddressType: discovery.AddressTypeIPv6,
|
|
+ Ports: []discovery.EndpointPort{{
|
|
+ Name: utilpointer.StringPtr("http"),
|
|
+ Protocol: protocolPtr(api.ProtocolTCP),
|
|
+ }},
|
|
+ Endpoints: []discovery.Endpoint{{
|
|
+ Addresses: []string{"fe80::9656:d028:8652:66b6"},
|
|
+ Hostname: utilpointer.StringPtr("valid-123"),
|
|
+ }},
|
|
+ },
|
|
+ },
|
|
}
|
|
|
|
for name, testCase := range testCases {
|
|
--
|
|
1.8.3.1
|
|
|