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 (v *WrappingValidator) ValidateUpdate(obj, old runtime.Object) fielderrors.ValidationErrorList { if v.validateUpdate == nil { // if there is no update validation, fail. return fielderrors.ValidationErrorList{fielderrors.NewFieldForbidden("obj", obj)} } return callValidateUpdate(reflect.ValueOf(obj), reflect.ValueOf(old), *v.validateUpdate) }
func ValidateDeploymentStrategy(strategy *experimental.DeploymentStrategy, fieldName string) errs.ValidationErrorList { allErrs := errs.ValidationErrorList{} if strategy.RollingUpdate == nil { return allErrs } switch strategy.Type { case experimental.RecreateDeploymentStrategyType: allErrs = append(allErrs, errs.NewFieldForbidden("rollingUpdate", "rollingUpdate should be nil when strategy type is "+experimental.RecreateDeploymentStrategyType)) case experimental.RollingUpdateDeploymentStrategyType: allErrs = append(allErrs, ValidateRollingUpdateDeployment(strategy.RollingUpdate, "rollingUpdate")...) } return allErrs }
func (v *TagVerifier) Verify(old, stream *api.ImageStream, user user.Info) fielderrors.ValidationErrorList { var errors fielderrors.ValidationErrorList oldTags := map[string]api.TagReference{} if old != nil && old.Spec.Tags != nil { oldTags = old.Spec.Tags } for tag, tagRef := range stream.Spec.Tags { if tagRef.From == nil { continue } if len(tagRef.From.Namespace) == 0 { continue } if stream.Namespace == tagRef.From.Namespace { continue } if oldRef, ok := oldTags[tag]; ok && !tagRefChanged(oldRef, tagRef, stream.Namespace) { continue } streamName, _, err := parseFromReference(stream, tagRef.From) if err != nil { errors = append(errors, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.tags[%s].from.name", tag), tagRef.From.Name, "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>")) continue } subjectAccessReview := authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Resource: "imagestreams", ResourceName: streamName, }, User: user.GetName(), Groups: sets.NewString(user.GetGroups()...), } ctx := kapi.WithNamespace(kapi.NewContext(), tagRef.From.Namespace) glog.V(4).Infof("Performing SubjectAccessReview for user=%s, groups=%v to %s/%s", user.GetName(), user.GetGroups(), tagRef.From.Namespace, streamName) resp, err := v.subjectAccessReviewClient.CreateSubjectAccessReview(ctx, &subjectAccessReview) if err != nil || resp == nil || (resp != nil && !resp.Allowed) { errors = append(errors, fielderrors.NewFieldForbidden(fmt.Sprintf("spec.tags[%s].from", tag), fmt.Sprintf("%s/%s", tagRef.From.Namespace, streamName))) continue } } return errors }
func TestTagVerifier(t *testing.T) { tests := map[string]struct { oldTags map[string]api.TagReference newTags map[string]api.TagReference sarError error sarAllowed bool expectSar bool expected fielderrors.ValidationErrorList }{ "old nil, no tags": {}, "old nil, all tags are new": { newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, expectSar: true, sarAllowed: true, }, "nil from": { newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "DockerImage", Name: "registry/old/stream:latest", }, }, }, expectSar: false, }, "same namespace": { newTags: map[string]api.TagReference{ "other": { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "namespace", Name: "otherstream:latest", }, }, }, }, "ref unchanged": { oldTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, expectSar: false, }, "invalid from name": { newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "a:b:c", }, }, }, expected: fielderrors.ValidationErrorList{ fielderrors.NewFieldInvalid("spec.tags[latest].from.name", "a:b:c", "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>"), }, }, "sar error": { newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, expectSar: true, sarError: errors.New("foo"), expected: fielderrors.ValidationErrorList{ fielderrors.NewFieldForbidden("spec.tags[latest].from", "otherns/otherstream"), }, }, "sar denied": { newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, expectSar: true, sarAllowed: false, expected: fielderrors.ValidationErrorList{ fielderrors.NewFieldForbidden("spec.tags[latest].from", "otherns/otherstream"), }, }, "ref changed": { oldTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:foo", }, }, }, newTags: map[string]api.TagReference{ api.DefaultImageTag: { From: &kapi.ObjectReference{ Kind: "ImageStreamTag", Namespace: "otherns", Name: "otherstream:latest", }, }, }, expectSar: true, sarAllowed: true, }, } for name, test := range tests { sar := &fakeSubjectAccessReviewRegistry{ err: test.sarError, allow: test.sarAllowed, } old := &api.ImageStream{ Spec: api.ImageStreamSpec{ Tags: test.oldTags, }, } stream := &api.ImageStream{ ObjectMeta: kapi.ObjectMeta{ Namespace: "namespace", Name: "stream", }, Spec: api.ImageStreamSpec{ Tags: test.newTags, }, } tagVerifier := &TagVerifier{sar} errs := tagVerifier.Verify(old, stream, &fakeUser{}) sarCalled := sar.request != nil if e, a := test.expectSar, sarCalled; e != a { t.Errorf("%s: expected SAR request=%t, got %t", name, e, a) } if test.expectSar { if e, a := "otherns", sar.requestNamespace; e != a { t.Errorf("%s: sar namespace: expected %v, got %v", name, e, a) } expectedSar := &authorizationapi.SubjectAccessReview{ Action: authorizationapi.AuthorizationAttributes{ Verb: "get", Resource: "imagestreams", ResourceName: "otherstream", }, User: "******", Groups: sets.NewString("group1"), } if e, a := expectedSar, sar.request; !reflect.DeepEqual(e, a) { t.Errorf("%s: unexpected SAR request: %s", name, util.ObjectDiff(e, a)) } } if e, a := test.expected, errs; !reflect.DeepEqual(e, a) { t.Errorf("%s: unexpected validation errors: %s", name, util.ObjectDiff(e, a)) } } }