Merge pull request #101084 from robscott/endpointslice-ip-validation

Updating EndpointSlice validation to match Endpoints validation
This commit is contained in:
Kubernetes Prow Robot 2021-04-16 17:10:21 -07:00 committed by GitHub
commit 889f1c3951
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 65 additions and 18 deletions

View File

@ -4266,7 +4266,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)...)
}
}
@ -5754,19 +5754,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).
//
// 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
// 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 {

View File

@ -17379,9 +17379,9 @@ func TestValidateNonSpecialIP(t *testing.T) {
{"ipv6", "2000::1"},
} {
t.Run(tc.desc, func(t *testing.T) {
errs := validateNonSpecialIP(tc.ip, fp)
errs := ValidateNonSpecialIP(tc.ip, fp)
if len(errs) != 0 {
t.Errorf("validateNonSpecialIP(%q, ...) = %v; want nil", tc.ip, errs)
t.Errorf("ValidateNonSpecialIP(%q, ...) = %v; want nil", tc.ip, errs)
}
})
}
@ -17399,9 +17399,9 @@ func TestValidateNonSpecialIP(t *testing.T) {
{"ipv6 local multicast", "ff02::"},
} {
t.Run(tc.desc, func(t *testing.T) {
errs := validateNonSpecialIP(tc.ip, fp)
errs := ValidateNonSpecialIP(tc.ip, fp)
if len(errs) == 0 {
t.Errorf("validateNonSpecialIP(%q, ...) = nil; want non-nil (errors)", tc.ip)
t.Errorf("ValidateNonSpecialIP(%q, ...) = nil; want non-nil (errors)", tc.ip)
}
})
}

View File

@ -100,8 +100,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)...)
}

View File

@ -53,6 +53,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{
@ -393,7 +408,7 @@ func TestValidateEndpointSlice(t *testing.T) {
},
},
"bad-ip": {
expectedErrors: 1,
expectedErrors: 2,
endpointSlice: &discovery.EndpointSlice{
ObjectMeta: standardMeta,
AddressType: discovery.AddressTypeIPv4,
@ -408,7 +423,7 @@ func TestValidateEndpointSlice(t *testing.T) {
},
},
"bad-ipv4": {
expectedErrors: 2,
expectedErrors: 3,
endpointSlice: &discovery.EndpointSlice{
ObjectMeta: standardMeta,
AddressType: discovery.AddressTypeIPv4,
@ -423,7 +438,7 @@ func TestValidateEndpointSlice(t *testing.T) {
},
},
"bad-ipv6": {
expectedErrors: 2,
expectedErrors: 4,
endpointSlice: &discovery.EndpointSlice{
ObjectMeta: standardMeta,
AddressType: discovery.AddressTypeIPv6,
@ -552,6 +567,36 @@ func TestValidateEndpointSlice(t *testing.T) {
}},
},
},
"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 {