Ejemplo n.º 1
0
func ValidateImageLabels(labels []buildapi.ImageLabel, fldPath *field.Path) (allErrs field.ErrorList) {
	for i, lbl := range labels {
		idxPath := fldPath.Index(i)
		if len(lbl.Name) == 0 {
			allErrs = append(allErrs, field.Required(idxPath.Child("name"), ""))
			continue
		}
		for _, msg := range kvalidation.IsConfigMapKey(lbl.Name) {
			allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), lbl.Name, msg))
		}
	}

	// find duplicates
	seen := make(map[string]bool)
	for i, lbl := range labels {
		idxPath := fldPath.Index(i)
		if seen[lbl.Name] {
			allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), lbl.Name, "duplicate name"))
			continue
		}
		seen[lbl.Name] = true
	}

	return
}
Ejemplo n.º 2
0
func ValidateDisabledFeatures(disabledFeatures []string, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for i, feature := range disabledFeatures {
		if _, isKnown := api.NormalizeOpenShiftFeature(feature); !isKnown {
			allErrs = append(allErrs, field.Invalid(fldPath.Index(i), disabledFeatures[i], fmt.Sprintf("not one of valid features: %s", strings.Join(api.KnownOpenShiftFeatures, ", "))))
		}
	}

	return allErrs
}
Ejemplo n.º 3
0
func validateHookVolumes(volumes []string, fldPath *field.Path) field.ErrorList {
	errs := field.ErrorList{}
	for i, vol := range volumes {
		vErrs := field.ErrorList{}
		if len(vol) == 0 {
			vErrs = append(vErrs, field.Invalid(fldPath.Index(i), "", "must not be empty"))
		}
		errs = append(errs, vErrs...)
	}
	return errs
}
Ejemplo n.º 4
0
func validateIngressTLS(spec *extensions.IngressSpec, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	// Currently the Ingress only supports HTTP(S), so a secretName is required.
	// This will not be the case if we support SSL routing at L4 via SNI.
	for i, t := range spec.TLS {
		if t.SecretName == "" {
			allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("secretName"), spec.TLS[i].SecretName))
		}
	}
	// TODO: Perform a more thorough validation of spec.TLS.Hosts that takes
	// the wildcard spec from RFC 6125 into account.
	return allErrs
}
Ejemplo n.º 5
0
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
}
Ejemplo n.º 6
0
func validateServiceAccountNames(serviceAccountNames []string, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	for i, sa := range serviceAccountNames {
		idxPath := fldPath.Index(i)
		switch {
		case len(sa) == 0:
			allErrs = append(allErrs, field.Invalid(idxPath, sa, ""))
		case len(sa) > 0:
			if reasons := kapivalidation.ValidateServiceAccountName(sa, false); len(reasons) != 0 {
				allErrs = append(allErrs, field.Invalid(idxPath, sa, strings.Join(reasons, ", ")))
			}
		}
	}
	return allErrs
}
Ejemplo n.º 7
0
// validatePodSecurityPolicySysctls validates the sysctls fields of PodSecurityPolicy.
func validatePodSecurityPolicySysctls(fldPath *field.Path, sysctls []string) field.ErrorList {
	allErrs := field.ErrorList{}
	for i, s := range sysctls {
		if !IsValidSysctlPattern(string(s)) {
			allErrs = append(
				allErrs,
				field.Invalid(fldPath.Index(i), sysctls[i], fmt.Sprintf("must have at most %d characters and match regex %s",
					apivalidation.SysctlMaxLength,
					SysctlPatternFmt,
				)),
			)
		}
	}

	return allErrs
}
Ejemplo n.º 8
0
func validateEnv(vars []kapi.EnvVar, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for i, ev := range vars {
		vErrs := field.ErrorList{}
		idxPath := fldPath.Index(i).Child("name")
		if len(ev.Name) == 0 {
			vErrs = append(vErrs, field.Required(idxPath, ""))
		}
		if errs := kvalidation.IsCIdentifier(ev.Name); len(errs) > 0 {
			vErrs = append(vErrs, field.Invalid(idxPath, ev.Name, strings.Join(errs, ", ")))
		}
		allErrs = append(allErrs, vErrs...)
	}
	return allErrs
}
Ejemplo n.º 9
0
func ValidateStrategyEnv(vars []kapi.EnvVar, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for i, ev := range vars {
		idxPath := fldPath.Index(i)
		if len(ev.Name) == 0 {
			allErrs = append(allErrs, field.Required(idxPath.Child("name"), ""))
		} else if !kvalidation.IsCIdentifier(ev.Name) {
			allErrs = append(allErrs, field.Invalid(idxPath.Child("name"), ev.Name, cIdentifierErrorMsg))
		}
		if ev.ValueFrom != nil {
			allErrs = append(allErrs, field.Invalid(idxPath.Child("valueFrom"), ev.ValueFrom, "valueFrom is not supported in build strategy environment variables"))
		}
	}
	return allErrs
}
Ejemplo n.º 10
0
func validateEnv(vars []kapi.EnvVar, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for i, ev := range vars {
		vErrs := field.ErrorList{}
		idxPath := fldPath.Index(i).Child("name")
		if len(ev.Name) == 0 {
			vErrs = append(vErrs, field.Required(idxPath, ""))
		}
		if !kvalidation.IsCIdentifier(ev.Name) {
			vErrs = append(vErrs, field.Invalid(idxPath, ev.Name, "must match regex "+kvalidation.CIdentifierFmt))
		}
		allErrs = append(allErrs, vErrs...)
	}
	return allErrs
}
Ejemplo n.º 11
0
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
}
Ejemplo n.º 12
0
func ValidateAPILevels(apiLevels []string, knownAPILevels, deadAPILevels []string, fldPath *field.Path) ValidationResults {
	validationResults := ValidationResults{}

	if len(apiLevels) == 0 {
		validationResults.AddErrors(field.Required(fldPath, ""))
	}

	deadLevels := sets.NewString(deadAPILevels...)
	knownLevels := sets.NewString(knownAPILevels...)
	for i, apiLevel := range apiLevels {
		idxPath := fldPath.Index(i)
		if deadLevels.Has(apiLevel) {
			validationResults.AddWarnings(field.Invalid(idxPath, apiLevel, "unsupported level"))
		}
		if !knownLevels.Has(apiLevel) {
			validationResults.AddWarnings(field.Invalid(idxPath, apiLevel, "unknown level"))
		}
	}

	return validationResults
}
Ejemplo n.º 13
0
// Ensures that `nil` can be passed to validation functions validating top-level objects
func TestNilPath(t *testing.T) {
	var nilPath *field.Path = nil
	if s := nilPath.String(); s != "" {
		t.Errorf("Unexpected nil path: %q", s)
	}

	child := nilPath.Child("child")
	if s := child.String(); s != "child" {
		t.Errorf("Unexpected child path: %q", s)
	}

	key := nilPath.Key("key")
	if s := key.String(); s != "[key]" {
		t.Errorf("Unexpected key path: %q", s)
	}

	index := nilPath.Index(1)
	if s := index.String(); s != "[1]" {
		t.Errorf("Unexpected index path: %q", s)
	}
}
Ejemplo n.º 14
0
func AccumulateUniqueHostPorts(containers []v1.Container, accumulator *sets.String, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for ci, ctr := range containers {
		idxPath := fldPath.Index(ci)
		portsPath := idxPath.Child("ports")
		for pi := range ctr.Ports {
			idxPath := portsPath.Index(pi)
			port := ctr.Ports[pi].HostPort
			if port == 0 {
				continue
			}
			str := fmt.Sprintf("%d/%s", port, ctr.Ports[pi].Protocol)
			if accumulator.Has(str) {
				allErrs = append(allErrs, field.Duplicate(idxPath.Child("hostPort"), str))
			} else {
				accumulator.Insert(str)
			}
		}
	}
	return allErrs
}
Ejemplo n.º 15
0
func validateSecrets(secrets []buildapi.SecretBuildSource, isDockerStrategy bool, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}
	for i, s := range secrets {
		if len(s.Secret.Name) == 0 {
			allErrs = append(allErrs, field.Required(fldPath.Index(i).Child("secret")))
		}
		if ok, _ := validation.ValidateSecretName(s.Secret.Name, false); !ok {
			allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("secret"), s, "must be valid secret name"))
		}
		if strings.HasPrefix(path.Clean(s.DestinationDir), "..") {
			allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("destinationDir"), s.DestinationDir, "destination dir cannot start with '..'"))
		}
		if isDockerStrategy && filepath.IsAbs(s.DestinationDir) {
			allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("destinationDir"), s.DestinationDir, "for the docker strategy the destinationDir has to be relative path"))
		}
	}
	return allErrs
}
Ejemplo n.º 16
0
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 {
			// TODO: Ports and ips are allowed in the host part of a url
			// according to RFC 3986, consider allowing them.
			if valid, errMsg := apivalidation.NameIsDNSSubdomain(ih.Host, false); !valid {
				allErrs = append(allErrs, field.Invalid(fldPath.Index(i).Child("host"), ih.Host, errMsg))
			}
			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"))
			}
		}
		allErrs = append(allErrs, validateIngressRuleValue(&ih.IngressRuleValue, fldPath.Index(0))...)
	}
	return allErrs
}
Ejemplo n.º 17
0
func ValidateScopes(scopes []string, fldPath *field.Path) field.ErrorList {
	allErrs := field.ErrorList{}

	for i, scope := range scopes {
		illegalCharacter := false
		// https://tools.ietf.org/html/rfc6749#section-3.3 (full list of allowed chars is %x21 / %x23-5B / %x5D-7E)
		// for those without an ascii table, that's `!`, `#-[`, `]-~` inclusive.
		for _, ch := range scope {
			switch {
			case ch == '!':
			case ch >= '#' && ch <= '[':
			case ch >= ']' && ch <= '~':
			default:
				allErrs = append(allErrs, field.Invalid(fldPath.Index(i), scope, fmt.Sprintf("%v not allowed", ch)))
				illegalCharacter = true
			}
		}
		if illegalCharacter {
			continue
		}

		found := false
		for _, evaluator := range authorizerscopes.ScopeEvaluators {
			if !evaluator.Handles(scope) {
				continue
			}

			found = true
			if err := evaluator.Validate(scope); err != nil {
				allErrs = append(allErrs, field.Invalid(fldPath.Index(i), scope, err.Error()))
				break
			}
		}

		if !found {
			allErrs = append(allErrs, field.Invalid(fldPath.Index(i), scope, "no scope handler found"))
		}
	}

	return allErrs
}
Ejemplo n.º 18
0
func objectReflectDiff(path *field.Path, a, b reflect.Value) []diff {
	switch a.Type().Kind() {
	case reflect.Struct:
		var changes []diff
		for i := 0; i < a.Type().NumField(); i++ {
			if !public(a.Type().Field(i).Name) {
				if reflect.DeepEqual(a.Interface(), b.Interface()) {
					return nil
				}
				return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}}
			}
			if sub := objectReflectDiff(path.Child(a.Type().Field(i).Name), a.Field(i), b.Field(i)); len(sub) > 0 {
				changes = append(changes, sub...)
			}
		}
		return changes
	case reflect.Ptr:
		if a.IsNil() || b.IsNil() {
			switch {
			case a.IsNil() && b.IsNil():
				return nil
			case a.IsNil():
				return []diff{{path: path, a: nil, b: b.Interface()}}
			default:
				return []diff{{path: path, a: a.Interface(), b: nil}}
			}
		}
		return objectReflectDiff(path, a.Elem(), b.Elem())
	case reflect.Chan:
		if !reflect.DeepEqual(a.Interface(), b.Interface()) {
			return []diff{{path: path, a: a.Interface(), b: b.Interface()}}
		}
		return nil
	case reflect.Slice:
		if reflect.DeepEqual(a, b) {
			return nil
		}
		lA, lB := a.Len(), b.Len()
		l := lA
		if lB < lA {
			l = lB
		}
		for i := 0; i < l; i++ {
			if !reflect.DeepEqual(a.Index(i), b.Index(i)) {
				return objectReflectDiff(path.Index(i), a.Index(i), b.Index(i))
			}
		}
		var diffs []diff
		for i := l; l < lA; i++ {
			diffs = append(diffs, diff{path: path.Index(i), a: a.Index(i), b: nil})
		}
		for i := l; l < lB; i++ {
			diffs = append(diffs, diff{path: path.Index(i), a: nil, b: b.Index(i)})
		}
		return diffs
	case reflect.Map:
		if reflect.DeepEqual(a, b) {
			return nil
		}
		aKeys := make(map[interface{}]interface{})
		for _, key := range a.MapKeys() {
			aKeys[key.Interface()] = a.MapIndex(key).Interface()
		}
		var missing []diff
		for _, key := range b.MapKeys() {
			if _, ok := aKeys[key.Interface()]; ok {
				delete(aKeys, key.Interface())
				if reflect.DeepEqual(a.MapIndex(key).Interface(), b.MapIndex(key).Interface()) {
					continue
				}
				missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key.Interface())), a: a.MapIndex(key).Interface(), b: b.MapIndex(key).Interface()})
				continue
			}
			missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key.Interface())), a: nil, b: b.MapIndex(key).Interface()})
		}
		for key, value := range aKeys {
			missing = append(missing, diff{path: path.Key(fmt.Sprintf("%s", key)), a: value, b: nil})
		}
		sort.Sort(orderedDiffs(missing))
		return missing
	default:
		if reflect.DeepEqual(a.Interface(), b.Interface()) {
			return nil
		}
		if !a.CanInterface() {
			return []diff{{path: path, a: fmt.Sprintf("%#v", a), b: fmt.Sprintf("%#v", b)}}
		}
		return []diff{{path: path, a: a.Interface(), b: b.Interface()}}
	}
}
Ejemplo n.º 19
0
func ValidateNamedCertificates(fldPath *field.Path, namedCertificates []api.NamedCertificate) ValidationResults {
	validationResults := ValidationResults{}

	takenNames := sets.NewString()
	for i, namedCertificate := range namedCertificates {
		idxPath := fldPath.Index(i)

		certDNSNames := []string{}
		if len(namedCertificate.CertFile) == 0 {
			validationResults.AddErrors(field.Required(idxPath.Child("certInfo"), ""))
		} else if certInfoErrors := ValidateCertInfo(namedCertificate.CertInfo, false, idxPath); len(certInfoErrors) > 0 {
			validationResults.AddErrors(certInfoErrors...)
		} else if cert, err := tls.LoadX509KeyPair(namedCertificate.CertFile, namedCertificate.KeyFile); err != nil {
			validationResults.AddErrors(field.Invalid(idxPath.Child("certInfo"), namedCertificate.CertInfo, fmt.Sprintf("error loading certificate/key: %v", err)))
		} else {
			leaf, _ := x509.ParseCertificate(cert.Certificate[0])
			certDNSNames = append(certDNSNames, leaf.Subject.CommonName)
			certDNSNames = append(certDNSNames, leaf.DNSNames...)
		}

		if len(namedCertificate.Names) == 0 {
			validationResults.AddErrors(field.Required(idxPath.Child("names"), ""))
		}
		for j, name := range namedCertificate.Names {
			jdxPath := idxPath.Child("names").Index(j)
			if len(name) == 0 {
				validationResults.AddErrors(field.Required(jdxPath, ""))
				continue
			}

			if takenNames.Has(name) {
				validationResults.AddErrors(field.Invalid(jdxPath, name, "this name is already used in another named certificate"))
				continue
			}

			// validate names as domain names or *.*.foo.com domain names
			validDNSName := true
			for _, s := range strings.Split(name, ".") {
				if s != "*" && len(utilvalidation.IsDNS1123Label(s)) != 0 {
					validDNSName = false
				}
			}
			if !validDNSName {
				validationResults.AddErrors(field.Invalid(jdxPath, name, "must be a valid DNS name"))
				continue
			}

			takenNames.Insert(name)

			// validate certificate has common name or subject alt names that match
			if len(certDNSNames) > 0 {
				foundMatch := false
				for _, dnsName := range certDNSNames {
					if cmdutil.HostnameMatches(dnsName, name) {
						foundMatch = true
						break
					}
					// if the cert has a wildcard dnsName, and we've configured a non-wildcard name, see if our specified name will match against the dnsName.
					if strings.HasPrefix(dnsName, "*.") && !strings.HasPrefix(name, "*.") && cmdutil.HostnameMatches(name, dnsName) {
						foundMatch = true
						break
					}
				}
				if !foundMatch {
					validationResults.AddWarnings(field.Invalid(jdxPath, name, "the specified certificate does not have a CommonName or DNS subjectAltName that matches this name"))
				}
			}
		}
	}

	return validationResults
}