func validateSessionConfig(config *api.SessionConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // Validate session secrets file, if specified sessionSecretsFilePath := fldPath.Child("sessionSecretsFile") if len(config.SessionSecretsFile) > 0 { fileErrs := ValidateFile(config.SessionSecretsFile, sessionSecretsFilePath) if len(fileErrs) != 0 { // Missing file allErrs = append(allErrs, fileErrs...) } else { // Validate file contents secrets, err := latest.ReadSessionSecrets(config.SessionSecretsFile) if err != nil { allErrs = append(allErrs, field.Invalid(sessionSecretsFilePath, config.SessionSecretsFile, fmt.Sprintf("error reading file: %v", err))) } else { for _, err := range ValidateSessionSecrets(secrets) { allErrs = append(allErrs, field.Invalid(sessionSecretsFilePath, config.SessionSecretsFile, err.Error())) } } } } if len(config.SessionName) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("sessionName"), "")) } return allErrs }
func validateBuildImageReference(reference *kapi.ObjectReference, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if reference != nil && reference.Kind != "DockerImage" { allErrs = append(allErrs, field.Invalid(fldPath.Child("kind"), reference.Kind, "only DockerImage references are supported for Builds")) } return allErrs }
func validateWebHook(webHook *buildapi.WebHookTrigger, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(webHook.Secret) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("secret"))) } return allErrs }
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 }
func validateDockerStrategy(strategy *buildapi.DockerBuildStrategy, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if strategy.From != nil { allErrs = append(allErrs, validateFromImageReference(strategy.From, fldPath.Child("from"))...) } allErrs = append(allErrs, validateSecretRef(strategy.PullSecret, fldPath.Child("pullSecret"))...) if len(strategy.DockerfilePath) != 0 { cleaned := path.Clean(strategy.DockerfilePath) switch { case strings.HasPrefix(cleaned, "/"): allErrs = append(allErrs, field.Invalid(fldPath.Child("dockerfilePath"), strategy.DockerfilePath, "dockerfilePath must not be an absolute path")) case strings.HasPrefix(cleaned, ".."): allErrs = append(allErrs, field.Invalid(fldPath.Child("dockerfilePath"), strategy.DockerfilePath, "dockerfilePath must not start with ..")) default: if cleaned == "." { cleaned = "" } strategy.DockerfilePath = cleaned } } allErrs = append(allErrs, ValidateStrategyEnv(strategy.Env, fldPath.Child("env"))...) return allErrs }
// validatePodSecurityPolicyVolumes validates the volume fields of PodSecurityPolicy. func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []extensions.FSType) field.ErrorList { allErrs := field.ErrorList{} allowed := sets.NewString(string(extensions.HostPath), string(extensions.EmptyDir), string(extensions.GCEPersistentDisk), string(extensions.AWSElasticBlockStore), string(extensions.GitRepo), string(extensions.Secret), string(extensions.NFS), string(extensions.ISCSI), string(extensions.Glusterfs), string(extensions.PersistentVolumeClaim), string(extensions.RBD), string(extensions.Cinder), string(extensions.CephFS), string(extensions.DownwardAPI), string(extensions.FC)) for _, v := range volumes { if !allowed.Has(string(v)) { allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List())) } } return allErrs }
func ValidateOpenIDIdentityProvider(provider *api.OpenIDIdentityProvider, identityProvider api.IdentityProvider, fieldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, fieldPath)...) // Communication with the Authorization Endpoint MUST utilize TLS // http://openid.net/specs/openid-connect-core-1_0.html#AuthorizationEndpoint providerPath := fieldPath.Child("provider") urlsPath := providerPath.Child("urls") _, urlErrs := ValidateSecureURL(provider.URLs.Authorize, urlsPath.Child("authorize")) allErrs = append(allErrs, urlErrs...) // Communication with the Token Endpoint MUST utilize TLS // http://openid.net/specs/openid-connect-core-1_0.html#TokenEndpoint _, urlErrs = ValidateSecureURL(provider.URLs.Token, urlsPath.Child("token")) allErrs = append(allErrs, urlErrs...) if len(provider.URLs.UserInfo) != 0 { // Communication with the UserInfo Endpoint MUST utilize TLS // http://openid.net/specs/openid-connect-core-1_0.html#UserInfo _, urlErrs = ValidateSecureURL(provider.URLs.UserInfo, urlsPath.Child("userInfo")) allErrs = append(allErrs, urlErrs...) } // At least one claim to use as the user id is required if len(provider.Claims.ID) == 0 { allErrs = append(allErrs, field.Invalid(providerPath.Child("claims", "id"), "[]", "at least one id claim is required (OpenID standard identity claim is 'sub')")) } if len(provider.CA) != 0 { allErrs = append(allErrs, ValidateFile(provider.CA, providerPath.Child("ca"))...) } return allErrs }
func validateIngressRuleValue(ingressRule *extensions.IngressRuleValue, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if ingressRule.HTTP != nil { allErrs = append(allErrs, validateHTTPIngressRuleValue(ingressRule.HTTP, fldPath.Child("http"))...) } return allErrs }
// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set. func ValidateDaemonSetSpec(spec *extensions.DaemonSetSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) if spec.Template == nil { allErrs = append(allErrs, field.Required(fldPath.Child("template"))) return allErrs } selector, err := extensions.LabelSelectorAsSelector(spec.Selector) if err == nil && !selector.Matches(labels.Set(spec.Template.Labels)) { allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "selector does not match template")) } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template, fldPath.Child("template"))...) // Daemons typically run on more than one node, so mark Read-Write persistent disks as invalid. allErrs = append(allErrs, apivalidation.ValidateReadOnlyPersistentDisks(spec.Template.Spec.Volumes, fldPath.Child("template", "spec", "volumes"))...) // RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } return allErrs }
func ValidateLDAPQuery(query api.LDAPQuery, fldPath *field.Path) ValidationResults { validationResults := ValidationResults{} if _, err := ldap.ParseDN(query.BaseDN); err != nil { validationResults.AddErrors(field.Invalid(fldPath.Child("baseDN"), query.BaseDN, fmt.Sprintf("invalid base DN for search: %v", err))) } if len(query.Scope) > 0 { if _, err := ldaputil.DetermineLDAPScope(query.Scope); err != nil { validationResults.AddErrors(field.Invalid(fldPath.Child("scope"), query.Scope, "invalid LDAP search scope")) } } if len(query.DerefAliases) > 0 { if _, err := ldaputil.DetermineDerefAliasesBehavior(query.DerefAliases); err != nil { validationResults.AddErrors(field.Invalid(fldPath.Child("derefAliases"), query.DerefAliases, "LDAP alias dereferencing instruction invalid")) } } if query.TimeLimit < 0 { validationResults.AddErrors(field.Invalid(fldPath.Child("timeout"), query.TimeLimit, "timeout must be equal to or greater than zero")) } if _, err := ldap.CompileFilter(query.Filter); err != nil { validationResults.AddErrors(field.Invalid(fldPath.Child("filter"), query.Filter, fmt.Sprintf("invalid query filter: %v", err))) } return validationResults }
func ValidateJobStatus(status *extensions.JobStatus, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Active), fldPath.Child("active"))...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Succeeded), fldPath.Child("succeeded"))...) allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(status.Failed), fldPath.Child("failed"))...) return allErrs }
func ValidateResourceRequirements(requirements *v1.ResourceRequirements, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} limPath := fldPath.Child("limits") reqPath := fldPath.Child("requests") for resourceName, quantity := range requirements.Limits { fldPath := limPath.Key(string(resourceName)) // Validate resource name. allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...) // Validate resource quantity. allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...) // Check that request <= limit. requestQuantity, exists := requirements.Requests[resourceName] if exists { // For GPUs, not only requests can't exceed limits, they also can't be lower, i.e. must be equal. if resourceName == v1.ResourceNvidiaGPU && quantity.Cmp(requestQuantity) != 0 { allErrs = append(allErrs, field.Invalid(reqPath, requestQuantity.String(), fmt.Sprintf("must be equal to %s limit", v1.ResourceNvidiaGPU))) } else if quantity.Cmp(requestQuantity) < 0 { allErrs = append(allErrs, field.Invalid(limPath, quantity.String(), fmt.Sprintf("must be greater than or equal to %s request", resourceName))) } } } for resourceName, quantity := range requirements.Requests { fldPath := reqPath.Key(string(resourceName)) // Validate resource name. allErrs = append(allErrs, validateContainerResourceName(string(resourceName), fldPath)...) // Validate resource quantity. allErrs = append(allErrs, ValidateResourceQuantityValue(string(resourceName), quantity, fldPath)...) } return allErrs }
func ValidatePodSecurityPolicySpecificAnnotations(annotations map[string]string, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if p := annotations[apparmor.DefaultProfileAnnotationKey]; p != "" { if err := apparmor.ValidateProfileFormat(p); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.DefaultProfileAnnotationKey), p, err.Error())) } } if allowed := annotations[apparmor.AllowedProfilesAnnotationKey]; allowed != "" { for _, p := range strings.Split(allowed, ",") { if err := apparmor.ValidateProfileFormat(p); err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Key(apparmor.AllowedProfilesAnnotationKey), allowed, err.Error())) } } } sysctlAnnotation := annotations[extensions.SysctlsPodSecurityPolicyAnnotationKey] sysctlFldPath := fldPath.Key(extensions.SysctlsPodSecurityPolicyAnnotationKey) sysctls, err := extensions.SysctlsFromPodSecurityPolicyAnnotation(sysctlAnnotation) if err != nil { allErrs = append(allErrs, field.Invalid(sysctlFldPath, sysctlAnnotation, err.Error())) } else { allErrs = append(allErrs, validatePodSecurityPolicySysctls(sysctlFldPath, sysctls)...) } if p := annotations[seccomp.DefaultProfileAnnotationKey]; p != "" { allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.DefaultProfileAnnotationKey))...) } if allowed := annotations[seccomp.AllowedProfilesAnnotationKey]; allowed != "" { for _, p := range strings.Split(allowed, ",") { allErrs = append(allErrs, apivalidation.ValidateSeccompProfile(p, fldPath.Key(seccomp.AllowedProfilesAnnotationKey))...) } } return allErrs }
func validateCustomParams(params *deployapi.CustomDeploymentStrategyParams, fldPath *field.Path) field.ErrorList { errs := field.ErrorList{} errs = append(errs, validateEnv(params.Environment, fldPath.Child("environment"))...) return errs }
// Validates given deployment spec. func ValidateDeploymentSpec(spec *extensions.DeploymentSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.Replicas), fldPath.Child("replicas"))...) if spec.Selector == nil { allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) } else { allErrs = append(allErrs, unversionedvalidation.ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) if len(spec.Selector.MatchLabels)+len(spec.Selector.MatchExpressions) == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "empty selector is not valid for deployment.")) } } selector, err := unversioned.LabelSelectorAsSelector(spec.Selector) if err != nil { allErrs = append(allErrs, field.Invalid(fldPath.Child("selector"), spec.Selector, "failed to convert LabelSelector to Selector.")) } else { allErrs = append(allErrs, ValidatePodTemplateSpecForReplicaSet(&spec.Template, selector, spec.Replicas, fldPath.Child("template"))...) } allErrs = append(allErrs, ValidateDeploymentStrategy(&spec.Strategy, fldPath.Child("strategy"))...) allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(spec.MinReadySeconds), fldPath.Child("minReadySeconds"))...) if spec.RevisionHistoryLimit != nil { // zero is a valid RevisionHistoryLimit allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.RevisionHistoryLimit), fldPath.Child("revisionHistoryLimit"))...) } if spec.RollbackTo != nil { allErrs = append(allErrs, ValidateRollback(spec.RollbackTo, fldPath.Child("rollback"))...) } return allErrs }
func ValidateEtcdConfig(config *api.EtcdConfig, fldPath *field.Path) ValidationResults { validationResults := ValidationResults{} servingInfoPath := fldPath.Child("servingInfo") validationResults.Append(ValidateServingInfo(config.ServingInfo, servingInfoPath)) if config.ServingInfo.BindNetwork == "tcp6" { validationResults.AddErrors(field.Invalid(servingInfoPath.Child("bindNetwork"), config.ServingInfo.BindNetwork, "tcp6 is not a valid bindNetwork for etcd, must be tcp or tcp4")) } if len(config.ServingInfo.NamedCertificates) > 0 { validationResults.AddErrors(field.Invalid(servingInfoPath.Child("namedCertificates"), "<not shown>", "namedCertificates are not supported for etcd")) } peerServingInfoPath := fldPath.Child("peerServingInfo") validationResults.Append(ValidateServingInfo(config.PeerServingInfo, peerServingInfoPath)) if config.ServingInfo.BindNetwork == "tcp6" { validationResults.AddErrors(field.Invalid(peerServingInfoPath.Child("bindNetwork"), config.ServingInfo.BindNetwork, "tcp6 is not a valid bindNetwork for etcd peers, must be tcp or tcp4")) } if len(config.ServingInfo.NamedCertificates) > 0 { validationResults.AddErrors(field.Invalid(peerServingInfoPath.Child("namedCertificates"), "<not shown>", "namedCertificates are not supported for etcd")) } validationResults.AddErrors(ValidateHostPort(config.Address, fldPath.Child("address"))...) validationResults.AddErrors(ValidateHostPort(config.PeerAddress, fldPath.Child("peerAddress"))...) if len(config.StorageDir) == 0 { validationResults.AddErrors(field.Required(fldPath.Child("storageDirectory"), "")) } return validationResults }
func ValidateJobSpec(spec *extensions.JobSpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if spec.Parallelism != nil { allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Parallelism), fldPath.Child("parallelism"))...) } if spec.Completions != nil { allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.Completions), fldPath.Child("completions"))...) } if spec.ActiveDeadlineSeconds != nil { allErrs = append(allErrs, apivalidation.ValidateNonnegativeField(int64(*spec.ActiveDeadlineSeconds), fldPath.Child("activeDeadlineSeconds"))...) } if spec.Selector == nil { allErrs = append(allErrs, field.Required(fldPath.Child("selector"), "")) } else { allErrs = append(allErrs, ValidateLabelSelector(spec.Selector, fldPath.Child("selector"))...) } if selector, err := extensions.LabelSelectorAsSelector(spec.Selector); err == nil { labels := labels.Set(spec.Template.Labels) if !selector.Matches(labels) { allErrs = append(allErrs, field.Invalid(fldPath.Child("template", "metadata", "labels"), spec.Template.Labels, "`selector` does not match template `labels`")) } } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template, fldPath.Child("template"))...) if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { allErrs = append(allErrs, field.NotSupported(fldPath.Child("template", "spec", "restartPolicy"), spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) } return allErrs }
func ValidateNetworkConfig(config api.NodeNetworkConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if config.MTU == 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("mtu"), config.MTU, fmt.Sprintf("must be greater than zero"))) } return allErrs }
func ValidateProjectLimitBySelector(limit api.ProjectLimitBySelector, path *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, unversionedvalidation.ValidateLabels(limit.Selector, path.Child("selector"))...) if limit.MaxProjects != nil && *limit.MaxProjects < 0 { allErrs = append(allErrs, field.Invalid(path.Child("maxProjects"), *limit.MaxProjects, "cannot be a negative number")) } return allErrs }
func ValidateClusterSpec(spec *federation.ClusterSpec, fieldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} // address is required. if len(spec.ServerAddressByClientCIDRs) == 0 { allErrs = append(allErrs, field.Required(fieldPath.Child("serverAddressByClientCIDRs"), "")) } return allErrs }
func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, validatePSPRunAsUser(fldPath.Child("runAsUser"), &spec.RunAsUser)...) allErrs = append(allErrs, validatePSPSELinuxContext(fldPath.Child("seLinuxContext"), &spec.SELinuxContext)...) allErrs = append(allErrs, validatePodSecurityPolicyVolumes(fldPath, spec.Volumes)...) return allErrs }
func validateGrantConfig(config api.GrantConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if !api.ValidGrantHandlerTypes.Has(string(config.Method)) { allErrs = append(allErrs, field.Invalid(fldPath.Child("method"), config.Method, fmt.Sprintf("must be one of: %v", api.ValidGrantHandlerTypes.List()))) } return allErrs }
func validateCustomParams(params *deployapi.CustomDeploymentStrategyParams, fldPath *field.Path) field.ErrorList { errs := field.ErrorList{} if len(params.Image) == 0 { errs = append(errs, field.Required(fldPath.Child("image"), "")) } return errs }
func ValidatePolicyConfig(config api.PolicyConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} allErrs = append(allErrs, ValidateFile(config.BootstrapPolicyFile, fldPath.Child("bootstrapPolicyFile"))...) allErrs = append(allErrs, ValidateNamespace(config.OpenShiftSharedResourcesNamespace, fldPath.Child("openShiftSharedResourcesNamespace"))...) allErrs = append(allErrs, ValidateNamespace(config.OpenShiftInfrastructureNamespace, fldPath.Child("openShiftInfrastructureNamespace"))...) return allErrs }
func ValidateImageConfig(config api.ImageConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if len(config.Format) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("format"), "")) } return allErrs }
// hasHostPort checks the port definitions on the container for HostPort > 0. func (s *simpleProvider) hasHostPort(container *api.Container, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, cp := range container.Ports { if cp.HostPort > 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPort"), cp.HostPort, "Host ports are not allowed to be used")) } } return allErrs }
func ValidateVolumeConfig(config api.VolumeConfig, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if config.LocalQuota.PerFSGroup != nil && config.LocalQuota.PerFSGroup.Value() < 0 { allErrs = append(allErrs, field.Invalid(fldPath.Child("localQuota", "perFSGroup"), config.LocalQuota.PerFSGroup, "must be a positive integer")) } return allErrs }
func validateSecretRef(ref *kapi.LocalObjectReference, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} if ref == nil { return allErrs } if len(ref.Name) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("name"))) } return allErrs }
func validateWebHook(webHook *buildapi.WebHookTrigger, fldPath *field.Path, isGeneric bool) field.ErrorList { allErrs := field.ErrorList{} if len(webHook.Secret) == 0 { allErrs = append(allErrs, field.Required(fldPath.Child("secret"), "")) } if !isGeneric && webHook.AllowEnv { allErrs = append(allErrs, field.Invalid(fldPath.Child("allowEnv"), webHook, "git webhooks cannot allow env vars")) } return allErrs }
// hasHostPort checks the port definitions on the container for HostPort > 0. func (s *simpleProvider) hasInvalidHostPort(container *api.Container, fldPath *field.Path) field.ErrorList { allErrs := field.ErrorList{} for _, cp := range container.Ports { if cp.HostPort > 0 && !s.isValidHostPort(int(cp.HostPort)) { detail := fmt.Sprintf("Host port %d is not allowed to be used. Allowed ports: %v", cp.HostPort, s.psp.Spec.HostPorts) allErrs = append(allErrs, field.Invalid(fldPath.Child("hostPort"), cp.HostPort, detail)) } } return allErrs }