diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go index e2453af72c4..d28453e2bb1 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation.go @@ -73,6 +73,8 @@ func Validate(config *kubeproxyconfig.KubeProxyConfiguration) field.ErrorList { allErrs = append(allErrs, field.Invalid(newPath.Child("PortRange"), config.PortRange, "must be a valid port range (e.g. 300-2000)")) } + allErrs = append(allErrs, validateKubeProxyNodePortAddress(config.NodePortAddresses, newPath.Child("NodePortAddresses"))...) + return allErrs } @@ -238,3 +240,16 @@ func validateIPVSSchedulerMethod(scheduler kubeproxyconfig.IPVSSchedulerMethod, } return allErrs } + +func validateKubeProxyNodePortAddress(nodePortAddresses []string, fldPath *field.Path) field.ErrorList { + allErrs := field.ErrorList{} + + for i := range nodePortAddresses { + if _, _, err := net.ParseCIDR(nodePortAddresses[i]); err != nil { + allErrs = append(allErrs, field.Invalid(fldPath, nodePortAddresses, "must be a valid IP block")) + break + } + } + + return allErrs +} diff --git a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go index 8815e0af077..aeb53a3e5a2 100644 --- a/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go +++ b/pkg/proxy/apis/kubeproxyconfig/validation/validation_test.go @@ -679,3 +679,73 @@ func TestValidateIPVSSchedulerMethod(t *testing.T) { } } } + +func TestValidateKubeProxyNodePortAddress(t *testing.T) { + newPath := field.NewPath("KubeProxyConfiguration") + + successCases := []struct { + addresses []string + }{ + {[]string{}}, + {[]string{"127.0.0.0/8"}}, + {[]string{"0.0.0.0/0"}}, + {[]string{"::/0"}}, + {[]string{"127.0.0.1/32", "1.2.3.0/24"}}, + {[]string{"127.0.0.0/8"}}, + {[]string{"127.0.0.1/32"}}, + {[]string{"::1/128"}}, + {[]string{"1.2.3.4/32"}}, + {[]string{"10.20.30.0/24"}}, + {[]string{"10.20.0.0/16", "100.200.0.0/16"}}, + {[]string{"10.0.0.0/8"}}, + {[]string{"2001:db8::/32"}}, + } + + for _, successCase := range successCases { + if errs := validateKubeProxyNodePortAddress(successCase.addresses, newPath.Child("NodePortAddresses")); len(errs) != 0 { + t.Errorf("expected success: %v", errs) + } + } + + errorCases := []struct { + addresses []string + msg string + }{ + { + addresses: []string{"foo"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"1.2.3"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{""}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"10.20.30.40"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"::1"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"2001:db8:1"}, + msg: "must be a valid IP block", + }, + { + addresses: []string{"2001:db8:xyz/64"}, + msg: "must be a valid IP block", + }, + } + + for _, errorCase := range errorCases { + if errs := validateKubeProxyNodePortAddress(errorCase.addresses, newPath.Child("NodePortAddresses")); len(errs) == 0 { + t.Errorf("expected failure for %s", errorCase.msg) + } else if !strings.Contains(errs[0].Error(), errorCase.msg) { + t.Errorf("unexpected error: %v, expected: %s", errs[0], errorCase.msg) + } + } +}