func validateImageChangeParams(params *deployapi.DeploymentTriggerImageChangeParams) fielderrors.ValidationErrorList { errs := fielderrors.ValidationErrorList{} if len(params.From.Name) != 0 { if len(params.From.Kind) == 0 { params.From.Kind = "ImageStream" } kinds := sets.NewString("ImageRepository", "ImageStream", "ImageStreamTag") if !kinds.Has(params.From.Kind) { msg := fmt.Sprintf("kind must be one of: %s", strings.Join(kinds.List(), ", ")) errs = append(errs, fielderrors.NewFieldInvalid("from.kind", params.From.Kind, msg)) } if !kvalidation.IsDNS1123Subdomain(params.From.Name) { errs = append(errs, fielderrors.NewFieldInvalid("from.name", params.From.Name, "name must be a valid subdomain")) } if len(params.From.Namespace) != 0 && !kvalidation.IsDNS1123Subdomain(params.From.Namespace) { errs = append(errs, fielderrors.NewFieldInvalid("from.namespace", params.From.Namespace, "namespace must be a valid subdomain")) } if len(params.RepositoryName) != 0 { errs = append(errs, fielderrors.NewFieldInvalid("repositoryName", params.RepositoryName, "only one of 'from', 'repository' name may be specified")) } } else { if len(params.RepositoryName) == 0 { errs = append(errs, fielderrors.NewFieldRequired("from")) } } if len(params.ContainerNames) == 0 { errs = append(errs, fielderrors.NewFieldRequired("containerNames")) } return errs }
func validateToImageReference(reference *kapi.ObjectReference) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} kind, name, namespace := reference.Kind, reference.Name, reference.Namespace switch kind { case "ImageStreamTag": if len(name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("name")) } else if _, _, ok := imageapi.SplitImageStreamTag(name); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", name, "ImageStreamTag object references must be in the form <name>:<tag>")) } if len(namespace) != 0 && !kvalidation.IsDNS1123Subdomain(namespace) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("namespace", namespace, "namespace must be a valid subdomain")) } case "DockerImage": if len(namespace) != 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("namespace", namespace, "namespace is not valid when used with a 'DockerImage'")) } if _, err := imageapi.ParseDockerImageReference(name); err != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", name, fmt.Sprintf("name is not a valid Docker pull specification: %v", err))) } case "": allErrs = append(allErrs, fielderrors.NewFieldRequired("kind")) default: allErrs = append(allErrs, fielderrors.NewFieldInvalid("kind", kind, "the target of build output must be an 'ImageStreamTag' or 'DockerImage'")) } return allErrs }
// ValidateRoute tests if required fields in the route are set. func ValidateRoute(route *routeapi.Route) fielderrors.ValidationErrorList { result := fielderrors.ValidationErrorList{} //ensure meta is set properly result = append(result, kval.ValidateObjectMeta(&route.ObjectMeta, true, oapi.GetNameValidationFunc(kval.ValidatePodName)).Prefix("metadata")...) //host is not required but if it is set ensure it meets DNS requirements if len(route.Spec.Host) > 0 { if !kvalidation.IsDNS1123Subdomain(route.Spec.Host) { result = append(result, fielderrors.NewFieldInvalid("host", route.Spec.Host, "host must conform to DNS 952 subdomain conventions")) } } if len(route.Spec.Path) > 0 && !strings.HasPrefix(route.Spec.Path, "/") { result = append(result, fielderrors.NewFieldInvalid("path", route.Spec.Path, "path must begin with /")) } if len(route.Spec.To.Name) == 0 { result = append(result, fielderrors.NewFieldRequired("serviceName")) } if route.Spec.Port != nil { switch target := route.Spec.Port.TargetPort; { case target.Kind == util.IntstrInt && target.IntVal == 0, target.Kind == util.IntstrString && len(target.StrVal) == 0: result = append(result, fielderrors.NewFieldRequired("targetPort")) } } if errs := validateTLS(route); len(errs) != 0 { result = append(result, errs.Prefix("tls")...) } return result }
func validateIngressRules(ingressRules []extensions.IngressRule, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(ingressRules) == 0 { return append(allErrs, field.Required(fldPath, "")) } for i, ih := range ingressRules { if len(ih.Host) > 0 { if isIP := (net.ParseIP(ih.Host) != nil); isIP { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, "must be a DNS name, not an IP address")) } // TODO: Ports and ips are allowed in the host part of a url // according to RFC 3986, consider allowing them. if strings.Contains(ih.Host, "*") { for _, msg := range validation.IsWildcardDNS1123Subdomain(ih.Host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg)) } continue } for _, msg := range validation.IsDNS1123Subdomain(ih.Host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, msg)) } } allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0))...) } return allErrs }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // Make sure event.Namespace and the involvedObject.Namespace agree if len(event.InvolvedObject.Namespace) == 0 { // event.Namespace must also be empty (or "default", for compatibility with old clients) if event.Namespace != api.NamespaceNone && event.Namespace != api.NamespaceDefault { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace")) } } else { // event namespace must match if event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match event.namespace")) } } // For kinds we recognize, make sure involvedObject.Namespace is set for namespaced kinds if namespaced, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion); err == nil { if namespaced && len(event.InvolvedObject.Namespace) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("involvedObject", "namespace"), fmt.Sprintf("required for kind %s", event.InvolvedObject.Kind))) } if !namespaced && len(event.InvolvedObject.Namespace) > 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for kind %s", event.InvolvedObject.Kind))) } } for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) } return allErrs }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // There is no namespace required for root-scoped kind, for example, node. // However, older client code accidentally sets event.Namespace // to api.NamespaceDefault, so we accept that too, but "" is preferred. // Todo: Events may reference 3rd party object, and we can't check whether the object is namespaced. // Suppose them are namespaced. Do check if we can get the piece of information. // This should apply to all groups served by this apiserver. namespacedKindFlag, err := isNamespacedKind(event.InvolvedObject.Kind, event.InvolvedObject.APIVersion) if err != nil { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "kind"), event.InvolvedObject.Kind, fmt.Sprintf("couldn't check whether namespace is allowed: %s", err))) } else { if !namespacedKindFlag && event.Namespace != api.NamespaceDefault && event.Namespace != "" { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, fmt.Sprintf("not allowed for %s", event.InvolvedObject.Kind))) } if namespacedKindFlag && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject")) } } if !validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, "")) } return allErrs }
// ValidateDomain checks the validity of a federation label. func ValidateDomain(name string) error { // The federation domain name need not strictly be domain names, we // accept valid dns names with subdomain components. if errs := validation.IsDNS1123Subdomain(name); len(errs) != 0 { return fmt.Errorf("%q not a valid domain name: %q", name, errs) } return nil }
// getNamedCertificateMap returns a map of strings to *tls.Certificate, suitable for use in // tls.Config#NamedCertificates. Returns an error if any of the certs cannot be loaded. // Returns nil if len(namedCertKeys) == 0 func getNamedCertificateMap(namedCertKeys []NamedCertKey) (map[string]*tls.Certificate, error) { if len(namedCertKeys) == 0 { return nil, nil } // load keys tlsCerts := make([]tls.Certificate, len(namedCertKeys)) for i := range namedCertKeys { var err error nkc := &namedCertKeys[i] tlsCerts[i], err = tls.LoadX509KeyPair(nkc.CertFile, nkc.KeyFile) if err != nil { return nil, err } } // register certs with implicit names first, reverse order such that earlier trump over the later tlsCertsByName := map[string]*tls.Certificate{} for i := len(namedCertKeys) - 1; i >= 0; i-- { nkc := &namedCertKeys[i] if len(nkc.Names) > 0 { continue } cert := &tlsCerts[i] // read names from certificate common names and DNS names if len(cert.Certificate) == 0 { return nil, fmt.Errorf("no certificate found in %q", nkc.CertFile) } x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) if err != nil { return nil, fmt.Errorf("parse error for certificate in %q: %v", nkc.CertFile, err) } cn := x509Cert.Subject.CommonName if cn == "*" || len(validation.IsDNS1123Subdomain(strings.TrimPrefix(cn, "*."))) == 0 { tlsCertsByName[cn] = cert } for _, san := range x509Cert.DNSNames { tlsCertsByName[san] = cert } // intentionally all IPs in the cert are ignored as SNI forbids passing IPs // to select a cert. Before go 1.6 the tls happily passed IPs as SNI values. } // register certs with explicit names last, overwriting every of the implicit ones, // again in reverse order. for i := len(namedCertKeys) - 1; i >= 0; i-- { nkc := &namedCertKeys[i] if len(nkc.Names) == 0 { continue } for _, name := range nkc.Names { tlsCertsByName[name] = &tlsCerts[i] } } return tlsCertsByName, nil }
func ValidateRoutingConfig(config api.RoutingConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(config.Subdomain) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("subdomain"), "")) } else if len(kuval.IsDNS1123Subdomain(config.Subdomain)) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("subdomain"), config.Subdomain, "must be a valid subdomain")) } return allErrs }
func ValidateRoutingConfig(config api.RoutingConfig) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(config.Subdomain) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("subdomain")) } else if !kuval.IsDNS1123Subdomain(config.Subdomain) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("subdomain", config.Subdomain, "must be a valid subdomain")) } return allErrs }
func ValidateDeploymentRequest(req *deployapi.DeploymentRequest) field.ErrorList { allErrs := field.ErrorList{} if len(req.Name) == 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("name"), req.Name, "name of the deployment config is missing")) } else if len(kvalidation.IsDNS1123Subdomain(req.Name)) != 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("name"), req.Name, "name of the deployment config is invalid")) } return allErrs }
func validateFromImageReference(reference *kapi.ObjectReference, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} kind, name, namespace := reference.Kind, reference.Name, reference.Namespace switch kind { case "ImageStreamTag": if len(name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) } else if _, _, ok := imageapi.SplitImageStreamTag(name); !ok { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), name, "ImageStreamTag object references must be in the form <name>:<tag>")) } else if name, _, _ := imageapi.SplitImageStreamTag(name); len(imageapivalidation.ValidateImageStreamName(name, false)) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), name, "ImageStreamTag name contains invalid syntax")) } if len(namespace) != 0 && len(kvalidation.IsDNS1123Subdomain(namespace)) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), namespace, "namespace must be a valid subdomain")) } case "DockerImage": if len(namespace) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), namespace, "namespace is not valid when used with a 'DockerImage'")) } if len(name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) } else if _, err := imageapi.ParseDockerImageReference(name); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("name"), name, fmt.Sprintf("name is not a valid Docker pull specification: %v", err))) } case "ImageStreamImage": if len(name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"), "")) } if len(namespace) != 0 && len(kvalidation.IsDNS1123Subdomain(namespace)) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("namespace"), namespace, "namespace must be a valid subdomain")) } case "": allErrs = append(allErrs, field.Required(fldPath.Child("kind"), "")) default: allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), kind, "the source of a builder image must be an 'ImageStreamTag', 'ImageStreamImage', or 'DockerImage'")) } return allErrs }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) validation.ErrorList { allErrs := validation.ErrorList{} // TODO: There is no namespace required for node. if event.InvolvedObject.Kind != "Node" && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, validation.NewInvalidError("involvedObject.namespace", event.InvolvedObject.Namespace, "namespace does not match involvedObject")) } if !validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, validation.NewInvalidError("namespace", event.Namespace, "")) } return allErrs }
// NewSimpleAllocationPlugin creates a new SimpleAllocationPlugin. func NewSimpleAllocationPlugin(suffix string) (*SimpleAllocationPlugin, error) { if len(suffix) == 0 { suffix = defaultDNSSuffix } glog.V(4).Infof("Route plugin initialized with suffix=%s", suffix) // Check that the DNS suffix is valid. if !kvalidation.IsDNS1123Subdomain(suffix) { return nil, fmt.Errorf("invalid DNS suffix: %s", suffix) } return &SimpleAllocationPlugin{DNSSuffix: suffix}, nil }
func ValidateAPIService(apiServer *discoveryapi.APIService) field.ErrorList { requiredName := apiServer.Spec.Version + "." + apiServer.Spec.Group allErrs := validation.ValidateObjectMeta(&apiServer.ObjectMeta, false, func(name string, prefix bool) []string { if minimalFailures := path.IsValidPathSegmentName(name); len(minimalFailures) > 0 { return minimalFailures } // the name *must* be version.group if name != requiredName { return []string{fmt.Sprintf("must be `spec.version+\".\"+spec.group`: %q", requiredName)} } return []string{} }, field.NewPath("metadata")) // in this case we allow empty group if len(apiServer.Spec.Group) == 0 && apiServer.Spec.Version != "v1" { allErrs = append(allErrs, field.Required(field.NewPath("spec", "group"), "only v1 may have an empty group and it better be legacy kube")) } if len(apiServer.Spec.Group) > 0 { for _, errString := range utilvalidation.IsDNS1123Subdomain(apiServer.Spec.Group) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "group"), apiServer.Spec.Group, errString)) } } for _, errString := range utilvalidation.IsDNS1035Label(apiServer.Spec.Version) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "version"), apiServer.Spec.Version, errString)) } if apiServer.Spec.Priority <= 0 || apiServer.Spec.Priority > 1000 { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "priority"), apiServer.Spec.Priority, "priority must be positive and less than 1000")) } if len(apiServer.Spec.Service.Namespace) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "namespace"), "")) } if len(apiServer.Spec.Service.Name) == 0 { allErrs = append(allErrs, field.Required(field.NewPath("spec", "service", "name"), "")) } if apiServer.Spec.InsecureSkipTLSVerify && len(apiServer.Spec.CABundle) > 0 { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "insecureSkipTLSVerify"), apiServer.Spec.InsecureSkipTLSVerify, "may not be true if caBundle is present")) } return allErrs }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // There is no namespace required for node. if event.InvolvedObject.Kind == "Node" && event.Namespace != "" { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "not required for node")) } if event.InvolvedObject.Kind != "Node" && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject")) } if !validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, "")) } return allErrs }
func ValidateDeploymentConfigRollback(rollback *deployapi.DeploymentConfigRollback) field.ErrorList { result := field.ErrorList{} if len(rollback.Name) == 0 { result = append(result, field.Required(field.NewPath("name"), "name of the deployment config is missing")) } else if len(kvalidation.IsDNS1123Subdomain(rollback.Name)) != 0 { result = append(result, field.Invalid(field.NewPath("name"), rollback.Name, "name of the deployment config is invalid")) } specPath := field.NewPath("spec") if rollback.Spec.Revision < 0 { result = append(result, field.Invalid(specPath.Child("revision"), rollback.Spec.Revision, "must be non-negative")) } return result }
// Set deserializes the input string in the format // "myfederation1=example.com,myfederation2=second.example.com,myfederation3=example.com" // into a map of key-value pairs of federation names to domain names. func (fv federationsVar) Set(keyVal string) error { for _, val := range strings.Split(keyVal, ",") { splits := strings.SplitN(strings.TrimSpace(val), "=", 2) name := strings.TrimSpace(splits[0]) domain := strings.TrimSpace(splits[1]) if len(validation.IsDNS1123Label(name)) != 0 { return fmt.Errorf("%s not a valid federation name", name) } // The federation domain name need not strictly be domain names, we // accept valid dns names with subdomain components. if len(validation.IsDNS1123Subdomain(domain)) != 0 { return fmt.Errorf("%s not a valid federation name", name) } fv.nameDomainMap[name] = domain } return nil }
// federationRecords checks if the given `queryPath` is for a federated service and if it is, // it returns a CNAME response containing the cluster zone name and federation domain name // suffix. func (kd *KubeDNS) federationRecords(queryPath []string) ([]skymsg.Service, error) { // `queryPath` is a reversed-array of the queried name, reverse it back to make it easy // to follow through this code and reduce confusion. There is no reason for it to be // reversed here. path := util.ReverseArray(queryPath) // Check if the name query matches the federation query pattern. if !kd.isFederationQuery(path) { return nil, etcd.Error{Code: etcd.ErrorCodeKeyNotFound} } // Now that we have already established that the query is a federation query, remove the local // domain path components, i.e. kd.domainPath, from the query. path = path[:len(path)-len(kd.domainPath)] // Append the zone name (zone in the cloud provider terminology, not a DNS // zone) and the region name. zone, region, err := kd.getClusterZoneAndRegion() if err != nil { return nil, fmt.Errorf("failed to obtain the cluster zone and region: %v", err) } path = append(path, zone, region) // We have already established that the map entry exists for the given federation, // we just need to retrieve the domain name, validate it and append it to the path. kd.configLock.RLock() domain := kd.config.Federations[path[2]] kd.configLock.RUnlock() // We accept valid subdomains as well, so just let all the valid subdomains. if len(validation.IsDNS1123Subdomain(domain)) != 0 { return nil, fmt.Errorf("%s is not a valid domain name for federation %s", domain, path[2]) } name := strings.Join(append(path, domain), ".") // Ensure that this name that we are returning as a CNAME response is a fully qualified // domain name so that the client's resolver library doesn't have to go through its // search list all over again. if !strings.HasSuffix(name, ".") { name = name + "." } return []skymsg.Service{{Host: name}}, nil }
// ValidateRoute tests if required fields in the route are set. func ValidateRoute(route *routeapi.Route) field.ErrorList { //ensure meta is set properly result := kval.ValidateObjectMeta(&route.ObjectMeta, true, oapi.GetNameValidationFunc(kval.ValidatePodName), field.NewPath("metadata")) specPath := field.NewPath("spec") //host is not required but if it is set ensure it meets DNS requirements if len(route.Spec.Host) > 0 { if !kvalidation.IsDNS1123Subdomain(route.Spec.Host) { result = append(result, field.Invalid(specPath.Child("host"), route.Spec.Host, "host must conform to DNS 952 subdomain conventions")) } } if len(route.Spec.Path) > 0 && !strings.HasPrefix(route.Spec.Path, "/") { result = append(result, field.Invalid(specPath.Child("path"), route.Spec.Path, "path must begin with /")) } if len(route.Spec.Path) > 0 && route.Spec.TLS != nil && route.Spec.TLS.Termination == routeapi.TLSTerminationPassthrough { result = append(result, field.Invalid(specPath.Child("path"), route.Spec.Path, "passthrough termination does not support paths")) } if len(route.Spec.To.Name) == 0 { result = append(result, field.Required(specPath.Child("to", "name"), "")) } if route.Spec.To.Kind != "Service" { result = append(result, field.Invalid(specPath.Child("to", "kind"), route.Spec.To.Kind, "must reference a Service")) } if route.Spec.Port != nil { switch target := route.Spec.Port.TargetPort; { case target.Type == intstr.Int && target.IntVal == 0, target.Type == intstr.String && len(target.StrVal) == 0: result = append(result, field.Required(specPath.Child("port", "targetPort"), "")) } } if errs := validateTLS(route, specPath.Child("tls")); len(errs) != 0 { result = append(result, errs...) } return result }
// ValidateEvent makes sure that the event makes sense. func ValidateEvent(event *api.Event) field.ErrorList { allErrs := field.ErrorList{} // There is no namespace required for node. // However, older client code accidentally sets event.Namespace // to api.NamespaceDefault, so we accept that too, but "" is preferred. if event.InvolvedObject.Kind == "Node" && event.Namespace != api.NamespaceDefault && event.Namespace != "" { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "not allowed for node")) } if event.InvolvedObject.Kind != "Node" && event.Namespace != event.InvolvedObject.Namespace { allErrs = append(allErrs, field.Invalid(field.NewPath("involvedObject", "namespace"), event.InvolvedObject.Namespace, "does not match involvedObject")) } for _, msg := range validation.IsDNS1123Subdomain(event.Namespace) { allErrs = append(allErrs, field.Invalid(field.NewPath("namespace"), event.Namespace, msg)) } return allErrs }
func validateIngressTLS(spec *extensions.IngressSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // TODO: Perform a more thorough validation of spec.TLS.Hosts that takes // the wildcard spec from RFC 6125 into account. for _, itls := range spec.TLS { for i, host := range itls.Hosts { if strings.Contains(host, "*") { for _, msg := range validation.IsWildcardDNS1123Subdomain(host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("hosts"), host, msg)) } continue } for _, msg := range validation.IsDNS1123Subdomain(host) { allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("hosts"), host, msg)) } } } return allErrs }
// getNamedCertificateMap returns a map of *tls.Certificate by name. It's is // suitable for use in tls.Config#NamedCertificates. Returns an error if any of the certs // cannot be loaded. Returns nil if len(certs) == 0 func getNamedCertificateMap(certs []namedTlsCert) (map[string]*tls.Certificate, error) { // register certs with implicit names first, reverse order such that earlier trump over the later byName := map[string]*tls.Certificate{} for i := len(certs) - 1; i >= 0; i-- { if len(certs[i].names) > 0 { continue } cert := &certs[i].tlsCert // read names from certificate common names and DNS names if len(cert.Certificate) == 0 { return nil, fmt.Errorf("empty SNI certificate, skipping") } x509Cert, err := x509.ParseCertificate(cert.Certificate[0]) if err != nil { return nil, fmt.Errorf("parse error for SNI certificate: %v", err) } cn := x509Cert.Subject.CommonName if cn == "*" || len(validation.IsDNS1123Subdomain(strings.TrimPrefix(cn, "*."))) == 0 { byName[cn] = cert } for _, san := range x509Cert.DNSNames { byName[san] = cert } // intentionally all IPs in the cert are ignored as SNI forbids passing IPs // to select a cert. Before go 1.6 the tls happily passed IPs as SNI values. } // register certs with explicit names last, overwriting every of the implicit ones, // again in reverse order. for i := len(certs) - 1; i >= 0; i-- { namedCert := &certs[i] for _, name := range namedCert.names { byName[name] = &certs[i].tlsCert } } return byName, nil }
// validate validates required fields are set to support structured generation func (s ServiceCommonGeneratorV1) validate() error { if len(s.Name) == 0 { return fmt.Errorf("name must be specified") } if len(s.Type) == 0 { return fmt.Errorf("type must be specified") } if s.ClusterIP == api.ClusterIPNone && s.Type != api.ServiceTypeClusterIP { return fmt.Errorf("ClusterIP=None can only be used with ClusterIP service type") } if s.ClusterIP == api.ClusterIPNone && len(s.TCP) > 0 { return fmt.Errorf("can not map ports with clusterip=None") } if s.ClusterIP != api.ClusterIPNone && len(s.TCP) == 0 && s.Type != api.ServiceTypeExternalName { return fmt.Errorf("at least one tcp port specifier must be provided") } if s.Type == api.ServiceTypeExternalName { if errs := validation.IsDNS1123Subdomain(s.ExternalName); len(errs) != 0 { return fmt.Errorf("invalid service external name %s", s.ExternalName) } } return nil }
// ValidateHostName checks that a route's host name satisfies DNS requirements. func ValidateHostName(route *routeapi.Route) field.ErrorList { result := field.ErrorList{} if len(route.Spec.Host) < 1 { return result } specPath := field.NewPath("spec") hostPath := specPath.Child("host") if len(kvalidation.IsDNS1123Subdomain(route.Spec.Host)) != 0 { result = append(result, field.Invalid(hostPath, route.Spec.Host, "host must conform to DNS 952 subdomain conventions")) } segments := strings.Split(route.Spec.Host, ".") for _, s := range segments { errs := kvalidation.IsDNS1123Label(s) for _, e := range errs { result = append(result, field.Invalid(hostPath, route.Spec.Host, e)) } } return result }
func ValidateRoleBinding(roleBinding *authorizationapi.RoleBinding, isNamespaced bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, isNamespaced, oapi.MinimalNameRequirements).Prefix("metadata")...) // roleRef namespace is empty when referring to global policy. if (len(roleBinding.RoleRef.Namespace) > 0) && !kvalidation.IsDNS1123Subdomain(roleBinding.RoleRef.Namespace) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleRef.namespace", roleBinding.RoleRef.Namespace, "roleRef.namespace must be a valid subdomain")) } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("roleRef.name")) } else { if valid, err := oapi.MinimalNameRequirements(roleBinding.RoleRef.Name, false); !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleRef.name", roleBinding.RoleRef.Name, err)) } } for i, subject := range roleBinding.Subjects { allErrs = append(allErrs, ValidateRoleBindingSubject(subject, isNamespaced).Prefix(fmt.Sprintf("subjects[%d]", i))...) } return allErrs }
func validateImageChangeParams(params *deployapi.DeploymentTriggerImageChangeParams) fielderrors.ValidationErrorList { errs := fielderrors.ValidationErrorList{} if len(params.From.Name) == 0 { errs = append(errs, fielderrors.NewFieldRequired("from")) } else { if params.From.Kind != "ImageStreamTag" { errs = append(errs, fielderrors.NewFieldInvalid("from.kind", params.From.Kind, "kind must be an ImageStreamTag")) } if err := validateImageStreamTagName(params.From.Name); err != nil { errs = append(errs, fielderrors.NewFieldInvalid("from.name", params.From.Name, err.Error())) } if len(params.From.Namespace) != 0 && !kvalidation.IsDNS1123Subdomain(params.From.Namespace) { errs = append(errs, fielderrors.NewFieldInvalid("from.namespace", params.From.Namespace, "namespace must be a valid subdomain")) } } if len(params.ContainerNames) == 0 { errs = append(errs, fielderrors.NewFieldRequired("containerNames")) } return errs }
func validateImageChangeParams(params *deployapi.DeploymentTriggerImageChangeParams, fldPath *field.Path) field.ErrorList { errs := field.ErrorList{} fromPath := fldPath.Child("from") if len(params.From.Name) == 0 { errs = append(errs, field.Required(fromPath, "")) } else { if params.From.Kind != "ImageStreamTag" { errs = append(errs, field.Invalid(fromPath.Child("kind"), params.From.Kind, "kind must be an ImageStreamTag")) } if err := validateImageStreamTagName(params.From.Name); err != nil { errs = append(errs, field.Invalid(fromPath.Child("name"), params.From.Name, err.Error())) } if len(params.From.Namespace) != 0 && !kvalidation.IsDNS1123Subdomain(params.From.Namespace) { errs = append(errs, field.Invalid(fromPath.Child("namespace"), params.From.Namespace, "namespace must be a valid subdomain")) } } if len(params.ContainerNames) == 0 { errs = append(errs, field.Required(fldPath.Child("containerNames"), "")) } return errs }
func validateRoleBinding(roleBinding *authorizationapi.RoleBinding, isNamespaced bool, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&roleBinding.ObjectMeta, isNamespaced, validation.ValidatePathSegmentName, fldPath.Child("metadata"))...) // roleRef namespace is empty when referring to global policy. if (len(roleBinding.RoleRef.Namespace) > 0) && len(kvalidation.IsDNS1123Subdomain(roleBinding.RoleRef.Namespace)) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("roleRef", "namespace"), roleBinding.RoleRef.Namespace, "roleRef.namespace must be a valid subdomain")) } if len(roleBinding.RoleRef.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("roleRef", "name"), "")) } else { if reasons := validation.ValidatePathSegmentName(roleBinding.RoleRef.Name, false); len(reasons) != 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("roleRef", "name"), roleBinding.RoleRef.Name, strings.Join(reasons, ", "))) } } subjectsPath := field.NewPath("subjects") for i, subject := range roleBinding.Subjects { allErrs = append(allErrs, validateRoleBindingSubject(subject, isNamespaced, subjectsPath.Index(i))...) } return allErrs }
// ValidateRoute tests if required fields in the route are set. func ValidateRoute(route *routeapi.Route) field.ErrorList { //ensure meta is set properly result := kval.ValidateObjectMeta(&route.ObjectMeta, true, oapi.GetNameValidationFunc(kval.ValidatePodName), field.NewPath("metadata")) specPath := field.NewPath("spec") //host is not required but if it is set ensure it meets DNS requirements if len(route.Spec.Host) > 0 { if len(kvalidation.IsDNS1123Subdomain(route.Spec.Host)) != 0 { result = append(result, field.Invalid(specPath.Child("host"), route.Spec.Host, "host must conform to DNS 952 subdomain conventions")) } } if len(route.Spec.Path) > 0 && !strings.HasPrefix(route.Spec.Path, "/") { result = append(result, field.Invalid(specPath.Child("path"), route.Spec.Path, "path must begin with /")) } if len(route.Spec.Path) > 0 && route.Spec.TLS != nil && route.Spec.TLS.Termination == routeapi.TLSTerminationPassthrough { result = append(result, field.Invalid(specPath.Child("path"), route.Spec.Path, "passthrough termination does not support paths")) } if len(route.Spec.To.Name) == 0 { result = append(result, field.Required(specPath.Child("to", "name"), "")) } if route.Spec.To.Kind != "Service" { result = append(result, field.Invalid(specPath.Child("to", "kind"), route.Spec.To.Kind, "must reference a Service")) } if route.Spec.To.Weight != nil && (*route.Spec.To.Weight < 0 || *route.Spec.To.Weight > 256) { result = append(result, field.Invalid(specPath.Child("to", "weight"), route.Spec.To.Weight, "weight must be an integer between 0 and 256")) } backendPath := specPath.Child("alternateBackends") if len(route.Spec.AlternateBackends) > 3 { result = append(result, field.Required(backendPath, "cannot specify more than 3 additional backends")) } for i, svc := range route.Spec.AlternateBackends { if len(svc.Name) == 0 { result = append(result, field.Required(backendPath.Index(i).Child("name"), "")) } if svc.Kind != "Service" { result = append(result, field.Invalid(backendPath.Index(i).Child("kind"), svc.Kind, "must reference a Service")) } if svc.Weight != nil && (*svc.Weight < 0 || *svc.Weight > 256) { result = append(result, field.Invalid(backendPath.Index(i).Child("weight"), svc.Weight, "weight must be an integer between 0 and 256")) } } if route.Spec.Port != nil { switch target := route.Spec.Port.TargetPort; { case target.Type == intstr.Int && target.IntVal == 0, target.Type == intstr.String && len(target.StrVal) == 0: result = append(result, field.Required(specPath.Child("port", "targetPort"), "")) } } if errs := validateTLS(route, specPath.Child("tls")); len(errs) != 0 { result = append(result, errs...) } return result }