func ValidateIdentity(identity *api.Identity) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} allErrs = append(allErrs, kvalidation.ValidateObjectMeta(&identity.ObjectMeta, false, ValidateIdentityName).Prefix("metadata")...) if len(identity.ProviderName) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("providerName")) } else if ok, msg := ValidateIdentityProviderName(identity.ProviderName); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid("providerName", identity.ProviderName, msg)) } if len(identity.ProviderUserName) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("providerUserName")) } else if ok, msg := ValidateIdentityProviderName(identity.ProviderUserName); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid("providerUserName", identity.ProviderUserName, msg)) } if len(identity.ProviderName) > 0 && len(identity.ProviderUserName) > 0 { expectedIdentityName := identity.ProviderName + ":" + identity.ProviderUserName if identity.Name != expectedIdentityName { allErrs = append(allErrs, fielderrors.NewFieldInvalid("user.name", identity.User.Name, fmt.Sprintf("must be %s", expectedIdentityName))) } } if ok, msg := ValidateUserName(identity.User.Name, false); !ok { allErrs = append(allErrs, fielderrors.NewFieldInvalid("user.name", identity.User.Name, msg)) } if len(identity.User.Name) == 0 && len(identity.User.UID) != 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("user.uid", identity.User.UID, "may not be set if user.name is empty")) } if len(identity.User.Name) != 0 && len(identity.User.UID) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("user.uid")) } return allErrs }
// ValidateDaemonSetSpec tests if required fields in the DaemonSetSpec are set. func ValidateDaemonSetSpec(spec *experimental.DaemonSetSpec) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} selector := labels.Set(spec.Selector).AsSelector() if selector.Empty() { allErrs = append(allErrs, errs.NewFieldRequired("selector")) } if spec.Template == nil { allErrs = append(allErrs, errs.NewFieldRequired("template")) } else { labels := labels.Set(spec.Template.Labels) if !selector.Matches(labels) { allErrs = append(allErrs, errs.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template).Prefix("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).Prefix("template.spec.volumes")...) // RestartPolicy has already been first-order validated as per ValidatePodTemplateSpec(). if spec.Template.Spec.RestartPolicy != api.RestartPolicyAlways { allErrs = append(allErrs, errs.NewFieldValueNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyAlways)})) } } return allErrs }
func validateStrategy(strategy *buildapi.BuildStrategy) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} switch { case len(strategy.Type) == 0: allErrs = append(allErrs, fielderrors.NewFieldRequired("type")) case strategy.Type == buildapi.SourceBuildStrategyType: if strategy.SourceStrategy == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("stiStrategy")) } else { allErrs = append(allErrs, validateSourceStrategy(strategy.SourceStrategy).Prefix("stiStrategy")...) } case strategy.Type == buildapi.DockerBuildStrategyType: if strategy.DockerStrategy == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("dockerStrategy")) } else { allErrs = append(allErrs, validateDockerStrategy(strategy.DockerStrategy).Prefix("dockerStrategy")...) } case strategy.Type == buildapi.CustomBuildStrategyType: if strategy.CustomStrategy == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("customStrategy")) } else { allErrs = append(allErrs, validateCustomStrategy(strategy.CustomStrategy).Prefix("customStrategy")...) } default: allErrs = append(allErrs, fielderrors.NewFieldInvalid("type", strategy.Type, "type is not in the enumerated list")) } return allErrs }
// ValidateImageStreamMapping tests required fields for an ImageStreamMapping. func ValidateImageStreamMapping(mapping *api.ImageStreamMapping) fielderrors.ValidationErrorList { result := fielderrors.ValidationErrorList{} result = append(result, validation.ValidateObjectMeta(&mapping.ObjectMeta, true, oapi.MinimalNameRequirements).Prefix("metadata")...) hasRepository := len(mapping.DockerImageRepository) != 0 hasName := len(mapping.Name) != 0 switch { case hasRepository: if _, err := api.ParseDockerImageReference(mapping.DockerImageRepository); err != nil { result = append(result, fielderrors.NewFieldInvalid("dockerImageRepository", mapping.DockerImageRepository, err.Error())) } case hasName: default: result = append(result, fielderrors.NewFieldRequired("name")) result = append(result, fielderrors.NewFieldRequired("dockerImageRepository")) } if ok, msg := validation.ValidateNamespaceName(mapping.Namespace, false); !ok { result = append(result, fielderrors.NewFieldInvalid("namespace", mapping.Namespace, msg)) } if len(mapping.Tag) == 0 { result = append(result, fielderrors.NewFieldRequired("tag")) } if errs := ValidateImage(&mapping.Image).Prefix("image"); len(errs) != 0 { result = append(result, errs...) } return result }
func ValidateNodeAuthConfig(config api.NodeAuthConfig) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(config.AuthenticationCacheTTL) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("authenticationCacheTTL")) } else if ttl, err := time.ParseDuration(config.AuthenticationCacheTTL); err != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authenticationCacheTTL", config.AuthenticationCacheTTL, fmt.Sprintf("%v", err))) } else if ttl < 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authenticationCacheTTL", config.AuthenticationCacheTTL, fmt.Sprintf("cannot be less than zero"))) } if config.AuthenticationCacheSize <= 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authenticationCacheSize", config.AuthenticationCacheSize, fmt.Sprintf("must be greater than zero"))) } if len(config.AuthorizationCacheTTL) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("authorizationCacheTTL")) } else if ttl, err := time.ParseDuration(config.AuthorizationCacheTTL); err != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authorizationCacheTTL", config.AuthorizationCacheTTL, fmt.Sprintf("%v", err))) } else if ttl < 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authorizationCacheTTL", config.AuthorizationCacheTTL, fmt.Sprintf("cannot be less than zero"))) } if config.AuthorizationCacheSize <= 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("authorizationCacheSize", config.AuthorizationCacheSize, fmt.Sprintf("must be greater than zero"))) } return allErrs }
func validateSource(input *buildapi.BuildSource) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} switch input.Type { case buildapi.BuildSourceGit: if input.Git == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("git")) } else { allErrs = append(allErrs, validateGitSource(input.Git).Prefix("git")...) } if input.Dockerfile != nil { allErrs = append(allErrs, fielderrors.NewFieldInvalid("dockerfile", "", "may not be set when type is Git")) } case buildapi.BuildSourceDockerfile: if input.Dockerfile == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("dockerfile")) } else { if len(*input.Dockerfile) > maxDockerfileLengthBytes { allErrs = append(allErrs, fielderrors.NewFieldInvalid("dockerfile", "", fmt.Sprintf("must be smaller than %d bytes", maxDockerfileLengthBytes))) } } if input.Git != nil { allErrs = append(allErrs, validateGitSource(input.Git).Prefix("git")...) } case "": allErrs = append(allErrs, fielderrors.NewFieldRequired("type")) } allErrs = append(allErrs, validateSecretRef(input.SourceSecret).Prefix("sourceSecret")...) return allErrs }
func ValidateJobSpec(spec *experimental.JobSpec) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if spec.Parallelism != nil && *spec.Parallelism < 0 { allErrs = append(allErrs, errs.NewFieldInvalid("parallelism", spec.Parallelism, isNegativeErrorMsg)) } if spec.Completions != nil && *spec.Completions < 0 { allErrs = append(allErrs, errs.NewFieldInvalid("completions", spec.Completions, isNegativeErrorMsg)) } selector := labels.Set(spec.Selector).AsSelector() if selector.Empty() { allErrs = append(allErrs, errs.NewFieldRequired("selector")) } if spec.Template == nil { allErrs = append(allErrs, errs.NewFieldRequired("template")) } else { labels := labels.Set(spec.Template.Labels) if !selector.Matches(labels) { allErrs = append(allErrs, errs.NewFieldInvalid("template.labels", spec.Template.Labels, "selector does not match template")) } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(spec.Template).Prefix("template")...) if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { allErrs = append(allErrs, errs.NewFieldValueNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) } } return allErrs }
func ValidateRFC2307Config(config *api.RFC2307Config) ValidationResults { validationResults := ValidationResults{} groupQueryResults := ValidateLDAPQuery("groupQuery", config.GroupQuery) validationResults.AddErrors(groupQueryResults.Errors...) validationResults.AddWarnings(groupQueryResults.Warnings...) if len(config.GroupNameAttributes) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("groupName")) } if len(config.GroupMembershipAttributes) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("groupMembership")) } userQueryResults := ValidateLDAPQuery("userQuery", config.UserQuery) validationResults.AddErrors(userQueryResults.Errors...) validationResults.AddWarnings(userQueryResults.Warnings...) if len(config.UserNameAttributes) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("userName")) } return validationResults }
// 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 !util.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 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 := util.NewStringSet("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 !util.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 && !util.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 }
func validateDeploymentStrategy(strategy *deployapi.DeploymentStrategy) fielderrors.ValidationErrorList { errs := fielderrors.ValidationErrorList{} if len(strategy.Type) == 0 { errs = append(errs, fielderrors.NewFieldRequired("type")) } switch strategy.Type { case deployapi.DeploymentStrategyTypeRecreate: if strategy.RecreateParams != nil { errs = append(errs, validateRecreateParams(strategy.RecreateParams).Prefix("recreateParams")...) } case deployapi.DeploymentStrategyTypeRolling: if strategy.RollingParams == nil { errs = append(errs, fielderrors.NewFieldRequired("rollingParams")) } else { errs = append(errs, validateRollingParams(strategy.RollingParams).Prefix("rollingParams")...) } case deployapi.DeploymentStrategyTypeCustom: if strategy.CustomParams == nil { errs = append(errs, fielderrors.NewFieldRequired("customParams")) } else { errs = append(errs, validateCustomParams(strategy.CustomParams).Prefix("customParams")...) } } // TODO: validate resource requirements (prereq: https://github.com/GoogleCloudPlatform/kubernetes/pull/7059) return errs }
func ValidateRoleBindingSubject(subject kapi.ObjectReference, isNamespaced bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(subject.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("name")) } if len(subject.UID) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("uid", subject.UID)) } if len(subject.APIVersion) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("apiVersion", subject.APIVersion)) } if len(subject.ResourceVersion) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("resourceVersion", subject.ResourceVersion)) } if len(subject.FieldPath) != 0 { allErrs = append(allErrs, fielderrors.NewFieldForbidden("fieldPath", subject.FieldPath)) } switch subject.Kind { case authorizationapi.ServiceAccountKind: if valid, reason := validation.ValidateServiceAccountName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } if !isNamespaced && len(subject.Namespace) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("namespace")) } case authorizationapi.UserKind: if valid, reason := uservalidation.ValidateUserName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } case authorizationapi.GroupKind: if valid, reason := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && !valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, reason)) } case authorizationapi.SystemUserKind: isValidSAName, _ := validation.ValidateServiceAccountName(subject.Name, false) isValidUserName, _ := uservalidation.ValidateUserName(subject.Name, false) if isValidSAName || isValidUserName { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, "conforms to User.name or ServiceAccount.name restrictions")) } case authorizationapi.SystemGroupKind: if valid, _ := uservalidation.ValidateGroupName(subject.Name, false); len(subject.Name) > 0 && valid { allErrs = append(allErrs, fielderrors.NewFieldInvalid("name", subject.Name, "conforms to Group.name restrictions")) } default: allErrs = append(allErrs, fielderrors.NewFieldValueNotSupported("kind", subject.Kind, []string{authorizationapi.ServiceAccountKind, authorizationapi.UserKind, authorizationapi.GroupKind, authorizationapi.SystemGroupKind, authorizationapi.SystemUserKind})) } return allErrs }
func ValidateRequestHeaderIdentityProvider(provider *api.RequestHeaderIdentityProvider, identityProvider api.IdentityProvider) ValidationResults { validationResults := ValidationResults{} if len(provider.ClientCA) > 0 { validationResults.AddErrors(ValidateFile(provider.ClientCA, "provider.clientCA")...) } if len(provider.Headers) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("provider.headers")) } if identityProvider.UseAsChallenger && len(provider.ChallengeURL) == 0 { err := fielderrors.NewFieldRequired("provider.challengeURL") err.Detail = "challengeURL is required if challenge=true" validationResults.AddErrors(err) } if identityProvider.UseAsLogin && len(provider.LoginURL) == 0 { err := fielderrors.NewFieldRequired("provider.loginURL") err.Detail = "loginURL is required if login=true" validationResults.AddErrors(err) } if len(provider.ChallengeURL) > 0 { url, urlErrs := ValidateURL(provider.ChallengeURL, "provider.challengeURL") validationResults.AddErrors(urlErrs...) if len(urlErrs) == 0 && !strings.Contains(url.RawQuery, redirector.URLToken) && !strings.Contains(url.RawQuery, redirector.QueryToken) { validationResults.AddWarnings( fielderrors.NewFieldInvalid( "provider.challengeURL", provider.ChallengeURL, fmt.Sprintf("query does not include %q or %q, redirect will not preserve original authorize parameters", redirector.URLToken, redirector.QueryToken), ), ) } } if len(provider.LoginURL) > 0 { url, urlErrs := ValidateURL(provider.LoginURL, "provider.loginURL") validationResults.AddErrors(urlErrs...) if len(urlErrs) == 0 && !strings.Contains(url.RawQuery, redirector.URLToken) && !strings.Contains(url.RawQuery, redirector.QueryToken) { validationResults.AddWarnings( fielderrors.NewFieldInvalid( "provider.loginURL", provider.LoginURL, fmt.Sprintf("query does not include %q or %q, redirect will not preserve original authorize parameters", redirector.URLToken, redirector.QueryToken), ), ) } } // Warn if it looks like they expect direct requests to the OAuth endpoints, and have not secured the header checking with a client certificate check if len(provider.ClientCA) == 0 && (len(provider.ChallengeURL) > 0 || len(provider.LoginURL) > 0) { validationResults.AddWarnings(fielderrors.NewFieldInvalid("provider.clientCA", "", "if no clientCA is set, no request verification is done, and any request directly against the OAuth server can impersonate any identity from this provider")) } return validationResults }
func ValidateResourceAccessReview(review *authorizationapi.ResourceAccessReview) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(review.Verb) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("verb")) } if len(review.Resource) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("resource")) } return allErrs }
func ValidateActiveDirectoryConfig(config *api.ActiveDirectoryConfig) ValidationResults { validationResults := ValidationResults{} validationResults.Append(ValidateLDAPQuery(config.AllUsersQuery).Prefix("usersQuery")) if len(config.UserNameAttributes) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("userNameAttributes")) } if len(config.GroupMembershipAttributes) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("groupMembershipAttributes")) } return validationResults }
func validateSource(input *buildapi.BuildSource) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if input.Type != buildapi.BuildSourceGit { allErrs = append(allErrs, fielderrors.NewFieldRequired("type")) } if input.Git == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("git")) } else { allErrs = append(allErrs, validateGitSource(input.Git).Prefix("git")...) } allErrs = append(allErrs, validateSecretRef(input.SourceSecret).Prefix("sourceSecret")...) return allErrs }
func ValidateUserIdentityMapping(mapping *api.UserIdentityMapping) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} allErrs = append(allErrs, kvalidation.ValidateObjectMeta(&mapping.ObjectMeta, false, ValidateIdentityName).Prefix("metadata")...) if len(mapping.Identity.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("identity.name")) } if mapping.Identity.Name != mapping.Name { allErrs = append(allErrs, fielderrors.NewFieldInvalid("identity.name", mapping.Identity.Name, "must match metadata.name")) } if len(mapping.User.Name) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("user.name")) } return allErrs }
func ValidateOAuthConfig(config *api.OAuthConfig) ValidationResults { validationResults := ValidationResults{} if len(config.MasterURL) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("masterURL")) } if _, urlErrs := ValidateURL(config.MasterPublicURL, "masterPublicURL"); len(urlErrs) > 0 { validationResults.AddErrors(urlErrs...) } if len(config.AssetPublicURL) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("assetPublicURL")) } if config.SessionConfig != nil { validationResults.AddErrors(ValidateSessionConfig(config.SessionConfig).Prefix("sessionConfig")...) } validationResults.AddErrors(ValidateGrantConfig(config.GrantConfig).Prefix("grantConfig")...) providerNames := util.NewStringSet() redirectingIdentityProviders := []string{} for i, identityProvider := range config.IdentityProviders { if identityProvider.UseAsLogin { redirectingIdentityProviders = append(redirectingIdentityProviders, identityProvider.Name) if api.IsPasswordAuthenticator(identityProvider) { if config.SessionConfig == nil { validationResults.AddErrors(fielderrors.NewFieldInvalid("sessionConfig", config, "sessionConfig is required if a password identity provider is used for browser based login")) } } } validationResults.Append(ValidateIdentityProvider(identityProvider).Prefix(fmt.Sprintf("identityProvider[%d]", i))) if len(identityProvider.Name) > 0 { if providerNames.Has(identityProvider.Name) { validationResults.AddErrors(fielderrors.NewFieldInvalid(fmt.Sprintf("identityProvider[%d].name", i), identityProvider.Name, "must have a unique name")) } providerNames.Insert(identityProvider.Name) } } if len(redirectingIdentityProviders) > 1 { validationResults.AddErrors(fielderrors.NewFieldInvalid("identityProviders", config.IdentityProviders, fmt.Sprintf("only one identity provider can support login for a browser, found: %v", redirectingIdentityProviders))) } return validationResults }
func ValidateIdentityProvider(identityProvider api.IdentityProvider) ValidationResults { validationResults := ValidationResults{} if len(identityProvider.Name) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("name")) } if ok, err := validation.ValidateIdentityProviderName(identityProvider.Name); !ok { validationResults.AddErrors(fielderrors.NewFieldInvalid("name", identityProvider.Name, err)) } if len(identityProvider.MappingMethod) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("mappingMethod")) } else if !validMappingMethods.Has(identityProvider.MappingMethod) { validationResults.AddErrors(fielderrors.NewFieldValueNotSupported("mappingMethod", identityProvider.MappingMethod, validMappingMethods.List())) } if !api.IsIdentityProviderType(identityProvider.Provider) { validationResults.AddErrors(fielderrors.NewFieldInvalid("provider", identityProvider.Provider, fmt.Sprintf("%v is invalid in this context", identityProvider.Provider))) } else { switch provider := identityProvider.Provider.Object.(type) { case (*api.RequestHeaderIdentityProvider): validationResults.Append(ValidateRequestHeaderIdentityProvider(provider, identityProvider)) case (*api.BasicAuthPasswordIdentityProvider): validationResults.AddErrors(ValidateRemoteConnectionInfo(provider.RemoteConnectionInfo).Prefix("provider")...) case (*api.HTPasswdPasswordIdentityProvider): validationResults.AddErrors(ValidateFile(provider.File, "provider.file")...) case (*api.LDAPPasswordIdentityProvider): validationResults.Append(ValidateLDAPIdentityProvider(provider)) case (*api.KeystonePasswordIdentityProvider): validationResults.Append(ValidateKeystoneIdentityProvider(provider, identityProvider).Prefix("provider")) case (*api.GitHubIdentityProvider): validationResults.AddErrors(ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...) case (*api.GoogleIdentityProvider): validationResults.AddErrors(ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...) case (*api.OpenIDIdentityProvider): validationResults.AddErrors(ValidateOpenIDIdentityProvider(provider, identityProvider)...) } } return validationResults }
func validateLifecycleHook(hook *deployapi.LifecycleHook) fielderrors.ValidationErrorList { errs := fielderrors.ValidationErrorList{} if len(hook.FailurePolicy) == 0 { errs = append(errs, fielderrors.NewFieldRequired("failurePolicy")) } if hook.ExecNewPod == nil { errs = append(errs, fielderrors.NewFieldRequired("execNewPod")) } else { errs = append(errs, validateExecNewPod(hook.ExecNewPod).Prefix("execNewPod")...) } return errs }
func ValidateOAuthIdentityProvider(clientID, clientSecret string, challenge bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(clientID) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("provider.clientID")) } if len(clientSecret) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("provider.clientSecret")) } if challenge { allErrs = append(allErrs, fielderrors.NewFieldInvalid("challenge", challenge, "oauth providers cannot be used for challenges")) } return allErrs }
func ValidateSessionConfig(config *api.SessionConfig) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} // Validate session secrets file, if specified if len(config.SessionSecretsFile) > 0 { fileErrs := ValidateFile(config.SessionSecretsFile, "sessionSecretsFile") 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, fielderrors.NewFieldInvalid("sessionSecretsFile", config.SessionSecretsFile, fmt.Sprintf("error reading file: %v", err))) } else { for _, err := range ValidateSessionSecrets(secrets) { allErrs = append(allErrs, fielderrors.NewFieldInvalid("sessionSecretsFile", config.SessionSecretsFile, err.Error())) } } } } if len(config.SessionName) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("sessionName")) } return allErrs }
// GenerateParameterValues generates Value for each Parameter of the given // Template that has Generate field specified where Value is not already // supplied. // // Examples: // // from | value // ----------------------------- // "test[0-9]{1}x" | "test7x" // "[0-1]{8}" | "01001100" // "0x[A-F0-9]{4}" | "0xB3AF" // "[a-zA-Z0-9]{8}" | "hW4yQU5i" func (p *Processor) GenerateParameterValues(t *api.Template) error { for i := range t.Parameters { param := &t.Parameters[i] if len(param.Value) > 0 { continue } if param.Generate != "" { generator, ok := p.Generators[param.Generate] if !ok { return fmt.Errorf("template.parameters[%v]: Unable to find the '%v' generator", i, param.Generate) } if generator == nil { return fmt.Errorf("template.parameters[%v]: Invalid '%v' generator", i, param.Generate) } value, err := generator.GenerateValue(param.From) if err != nil { return err } param.Value, ok = value.(string) if !ok { return fmt.Errorf("template.parameters[%v]: Unable to convert the generated value '%#v' to string", i, value) } } if len(param.Value) == 0 && param.Required { err := fielderrors.NewFieldRequired(fmt.Sprintf("parameters[%d].value", i)) err.Detail = fmt.Sprintf("parameter %s is required and must be specified") return err } } return nil }
func ValidateNodeConfig(config *api.NodeConfig) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(config.NodeName) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("nodeName")) } if len(config.NodeIP) > 0 { allErrs = append(allErrs, ValidateSpecifiedIP(config.NodeIP, "nodeIP")...) } allErrs = append(allErrs, ValidateServingInfo(config.ServingInfo).Prefix("servingInfo")...) if config.ServingInfo.BindNetwork == "tcp6" { allErrs = append(allErrs, fielderrors.NewFieldInvalid("servingInfo.bindNetwork", config.ServingInfo.BindNetwork, "tcp6 is not a valid bindNetwork for nodes, must be tcp or tcp4")) } allErrs = append(allErrs, ValidateKubeConfig(config.MasterKubeConfig, "masterKubeConfig")...) if len(config.DNSIP) > 0 { allErrs = append(allErrs, ValidateSpecifiedIP(config.DNSIP, "dnsIP")...) } allErrs = append(allErrs, ValidateImageConfig(config.ImageConfig).Prefix("imageConfig")...) if config.PodManifestConfig != nil { allErrs = append(allErrs, ValidatePodManifestConfig(config.PodManifestConfig).Prefix("podManifestConfig")...) } allErrs = append(allErrs, ValidateNetworkConfig(config.NetworkConfig).Prefix("networkConfig")...) allErrs = append(allErrs, ValidateDockerConfig(config.DockerConfig).Prefix("dockerConfig")...) allErrs = append(allErrs, ValidateKubeletExtendedArguments(config.KubeletArguments).Prefix("kubeletArguments")...) return allErrs }
func ValidatePolicyBinding(policyBinding *authorizationapi.PolicyBinding, isNamespaced bool) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} allErrs = append(allErrs, validation.ValidateObjectMeta(&policyBinding.ObjectMeta, isNamespaced, PolicyBindingNameValidator(policyBinding.PolicyRef.Namespace)).Prefix("metadata")...) if !isNamespaced { if len(policyBinding.PolicyRef.Namespace) > 0 { allErrs = append(allErrs, fielderrors.NewFieldInvalid("policyRef.namespace", policyBinding.PolicyRef.Namespace, "may not reference another namespace")) } } for roleBindingKey, roleBinding := range policyBinding.RoleBindings { if roleBinding == nil { allErrs = append(allErrs, fielderrors.NewFieldRequired("roleBindings."+roleBindingKey)) } if roleBinding.RoleRef.Namespace != policyBinding.PolicyRef.Namespace { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleBindings."+roleBindingKey+".roleRef.namespace", policyBinding.PolicyRef.Namespace, "must be "+policyBinding.PolicyRef.Namespace)) } if roleBindingKey != roleBinding.Name { allErrs = append(allErrs, fielderrors.NewFieldInvalid("roleBindings."+roleBindingKey+".metadata.name", roleBinding.Name, "must be "+roleBindingKey)) } allErrs = append(allErrs, ValidateRoleBinding(roleBinding, isNamespaced).Prefix("roleBindings."+roleBindingKey)...) } return allErrs }
func ValidateJobSpec(spec *extensions.JobSpec) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if spec.Parallelism != nil { allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Parallelism), "parallelism")...) } if spec.Completions != nil { allErrs = append(allErrs, apivalidation.ValidatePositiveField(int64(*spec.Completions), "completions")...) } if spec.Selector == nil { allErrs = append(allErrs, errs.NewFieldRequired("selector")) } else { allErrs = append(allErrs, ValidatePodSelector(spec.Selector).Prefix("selector")...) } if selector, err := extensions.PodSelectorAsSelector(spec.Selector); err == nil { labels := labels.Set(spec.Template.Labels) if !selector.Matches(labels) { allErrs = append(allErrs, errs.NewFieldInvalid("template.metadata.labels", spec.Template.Labels, "selector does not match template")) } } allErrs = append(allErrs, apivalidation.ValidatePodTemplateSpec(&spec.Template).Prefix("template")...) if spec.Template.Spec.RestartPolicy != api.RestartPolicyOnFailure && spec.Template.Spec.RestartPolicy != api.RestartPolicyNever { allErrs = append(allErrs, errs.NewFieldValueNotSupported("template.spec.restartPolicy", spec.Template.Spec.RestartPolicy, []string{string(api.RestartPolicyOnFailure), string(api.RestartPolicyNever)})) } return allErrs }
func ValidateEtcdConfig(config *api.EtcdConfig) ValidationResults { validationResults := ValidationResults{} validationResults.Append(ValidateServingInfo(config.ServingInfo).Prefix("servingInfo")) if config.ServingInfo.BindNetwork == "tcp6" { validationResults.AddErrors(fielderrors.NewFieldInvalid("servingInfo.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(fielderrors.NewFieldInvalid("servingInfo.namedCertificates", "<not shown>", "namedCertificates are not supported for etcd")) } validationResults.Append(ValidateServingInfo(config.PeerServingInfo).Prefix("peerServingInfo")) if config.ServingInfo.BindNetwork == "tcp6" { validationResults.AddErrors(fielderrors.NewFieldInvalid("peerServingInfo.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(fielderrors.NewFieldInvalid("peerServingInfo.namedCertificates", "<not shown>", "namedCertificates are not supported for etcd")) } validationResults.AddErrors(ValidateHostPort(config.Address, "address")...) validationResults.AddErrors(ValidateHostPort(config.PeerAddress, "peerAddress")...) if len(config.StorageDir) == 0 { validationResults.AddErrors(fielderrors.NewFieldRequired("storageDirectory")) } return validationResults }
func validateWebHook(webHook *buildapi.WebHookTrigger) fielderrors.ValidationErrorList { allErrs := fielderrors.ValidationErrorList{} if len(webHook.Secret) == 0 { allErrs = append(allErrs, fielderrors.NewFieldRequired("secret")) } return allErrs }
func validateHTTPIngressRuleValue(httpIngressRuleValue *extensions.HTTPIngressRuleValue) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if len(httpIngressRuleValue.Paths) == 0 { allErrs = append(allErrs, errs.NewFieldRequired("paths")) } for _, rule := range httpIngressRuleValue.Paths { if len(rule.Path) > 0 { if !strings.HasPrefix(rule.Path, "/") { allErrs = append(allErrs, errs.NewFieldInvalid("path", rule.Path, "path must begin with /")) } // TODO: More draconian path regex validation. // Path must be a valid regex. This is the basic requirement. // In addition to this any characters not allowed in a path per // RFC 3986 section-3.3 cannot appear as a literal in the regex. // Consider the example: http://host/valid?#bar, everything after // the last '/' is a valid regex that matches valid#bar, which // isn't a valid path, because the path terminates at the first ? // or #. A more sophisticated form of validation would detect that // the user is confusing url regexes with path regexes. _, err := regexp.CompilePOSIX(rule.Path) if err != nil { allErrs = append(allErrs, errs.NewFieldInvalid("path", rule.Path, "httpIngressRuleValue.path must be a valid regex.")) } } allErrs = append(allErrs, validateIngressBackend(&rule.Backend).Prefix("backend")...) } return allErrs }