diff --git a/pkg/api/validation/validation.go b/pkg/api/validation/validation.go index f85b398cc4fe0..acb1ffd008e6b 100644 --- a/pkg/api/validation/validation.go +++ b/pkg/api/validation/validation.go @@ -758,6 +758,14 @@ func ValidateService(service *api.Service) errs.ValidationErrorList { } } + for _, ip := range service.Spec.PublicIPs { + if ip == "0.0.0.0" { + allErrs = append(allErrs, errs.NewFieldInvalid("spec.publicIPs", ip, "is not an IP address")) + } else if util.IsValidIP(ip) && net.ParseIP(ip).IsLoopback() { + allErrs = append(allErrs, errs.NewFieldInvalid("spec.publicIPs", ip, "publicIP cannot be a loopback")) + } + } + return allErrs } diff --git a/pkg/api/validation/validation_test.go b/pkg/api/validation/validation_test.go index c656c548a87df..10fe77825644d 100644 --- a/pkg/api/validation/validation_test.go +++ b/pkg/api/validation/validation_test.go @@ -1170,6 +1170,27 @@ func TestValidateService(t *testing.T) { }, numErrs: 1, }, + { + name: "invalid publicIPs localhost", + makeSvc: func(s *api.Service) { + s.Spec.PublicIPs = []string{"127.0.0.1"} + }, + numErrs: 1, + }, + { + name: "invalid publicIPs", + makeSvc: func(s *api.Service) { + s.Spec.PublicIPs = []string{"0.0.0.0"} + }, + numErrs: 1, + }, + { + name: "valid publicIPs host", + makeSvc: func(s *api.Service) { + s.Spec.PublicIPs = []string{"myhost.mydomain"} + }, + numErrs: 0, + }, { name: "nil selector", makeSvc: func(s *api.Service) { diff --git a/pkg/util/validation.go b/pkg/util/validation.go index 73a59e2bbf533..2adae39c6920d 100644 --- a/pkg/util/validation.go +++ b/pkg/util/validation.go @@ -17,6 +17,7 @@ limitations under the License. package util import ( + "net" "regexp" ) @@ -94,3 +95,8 @@ func IsCIdentifier(value string) bool { func IsValidPortNum(port int) bool { return 0 < port && port < 65536 } + +// IsValidIP tests that the argument is a valid IPv4 address. +func IsValidIP(value string) bool { + return net.ParseIP(value) != nil && net.ParseIP(value).To4() != nil +} diff --git a/pkg/util/validation_test.go b/pkg/util/validation_test.go index 61c7061a8d90c..853b0932d9c60 100644 --- a/pkg/util/validation_test.go +++ b/pkg/util/validation_test.go @@ -222,3 +222,33 @@ func TestIsValidLabelValue(t *testing.T) { } } } + +func TestIsValidIP(t *testing.T) { + goodValues := []string{ + "1.1.1.1", + "1.1.1.01", + "255.0.0.1", + "1.0.0.0", + "0.0.0.0", + } + for _, val := range goodValues { + if !IsValidIP(val) { + t.Errorf("expected true for %q", val) + } + } + + badValues := []string{ + "2a00:79e0:2:0:f1c3:e797:93c1:df80", // This is valid IPv6 + "a", + "myhost.mydomain", + "-1.0.0.0", + "1.0.0.256", + "1.0.0.1.1", + "1.0.0.1.", + } + for _, val := range badValues { + if IsValidIP(val) { + t.Errorf("expected false for %q", val) + } + } +}