From 89ebf476404d8a9fec6bb7e71344debf5a40dd77 Mon Sep 17 00:00:00 2001 From: Bowei Du Date: Tue, 6 Apr 2021 09:58:55 -0700 Subject: [PATCH] Update IP address validation message to include IPv6 Adds unit test Change-Id: I08c46f68b164e1ea82bf40f8a1316dfc1e95a6fb --- pkg/apis/core/validation/validation.go | 12 ++++--- pkg/apis/core/validation/validation_test.go | 40 +++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index 57292c5f367..3f41861341a 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -5764,6 +5764,10 @@ func validateNonSpecialIP(ipAddress string, fldPath *field.Path) field.ErrorList // 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 allErrs := field.ErrorList{} ip := net.ParseIP(ipAddress) if ip == nil { @@ -5771,16 +5775,16 @@ func validateNonSpecialIP(ipAddress string, fldPath *field.Path) field.ErrorList return allErrs } if ip.IsUnspecified() { - allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be unspecified (0.0.0.0)")) + allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, fmt.Sprintf("may not be unspecified (%v)", ipAddress))) } if ip.IsLoopback() { - allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the loopback range (127.0.0.0/8)")) + allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the loopback range (127.0.0.0/8, ::1/128)")) } if ip.IsLinkLocalUnicast() { - allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the link-local range (169.254.0.0/16)")) + allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the link-local range (169.254.0.0/16, fe80::/10)")) } if ip.IsLinkLocalMulticast() { - allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the link-local multicast range (224.0.0.0/24)")) + allErrs = append(allErrs, field.Invalid(fldPath, ipAddress, "may not be in the link-local multicast range (224.0.0.0/24, ff02::/10)")) } return allErrs } diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index f17da52307c..7ca8a26c870 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -17366,3 +17366,43 @@ func TestValidateResourceRequirements(t *testing.T) { }) } } + +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) + } + }) + } +}