Пример #1
0
func (v *TagVerifier) Verify(old, stream *api.ImageStream, user user.Info) field.ErrorList {
	var errors field.ErrorList
	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)
		fromPath := field.NewPath("spec", "tags").Key(tag).Child("from")
		if err != nil {
			errors = append(errors, field.Invalid(fromPath.Child("name"), tagRef.From.Name, "must be of the form <tag>, <repo>:<tag>, <id>, or <repo>@<id>"))
			continue
		}

		// Make sure this user can pull the specified image before allowing them to tag it into another imagestream
		subjectAccessReview := authorizationapi.AddUserToSAR(user, &authorizationapi.SubjectAccessReview{
			Action: authorizationapi.Action{
				Verb:         "get",
				Group:        api.GroupName,
				Resource:     "imagestreams/layers",
				ResourceName: streamName,
			},
		})
		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, field.Forbidden(fromPath, fmt.Sprintf("%s/%s", tagRef.From.Namespace, streamName)))
			continue
		}
	}
	return errors
}
Пример #2
0
func (r *RemoteAuthorizer) Authorize(ctx kapi.Context, a authorizer.AuthorizationAttributes) (bool, string, error) {
	var (
		result *authzapi.SubjectAccessReviewResponse
		err    error
	)

	// Extract namespace from context
	namespace, _ := kapi.NamespaceFrom(ctx)

	// Extract user from context
	user := ""
	groups := sets.NewString()
	userInfo, ok := kapi.UserFrom(ctx)
	if ok {
		user = userInfo.GetName()
		groups.Insert(userInfo.GetGroups()...)
	}

	// Make sure we don't run a subject access review on our own permissions
	if len(user) == 0 && len(groups) == 0 {
		user = bootstrappolicy.UnauthenticatedUsername
		groups = sets.NewString(bootstrappolicy.UnauthenticatedGroup)
	}

	if len(namespace) > 0 {
		result, err = r.client.LocalSubjectAccessReviews(namespace).Create(
			authzapi.AddUserToLSAR(userInfo, &authzapi.LocalSubjectAccessReview{Action: getAction(namespace, a)}))
	} else {
		result, err = r.client.SubjectAccessReviews().Create(
			authzapi.AddUserToSAR(userInfo, &authzapi.SubjectAccessReview{Action: getAction(namespace, a)}))
	}

	if err != nil {
		glog.Errorf("error running subject access review: %v", err)
		return false, "", kerrs.NewInternalError(err)
	}
	glog.V(2).Infof("allowed=%v, reason=%s", result.Allowed, result.Reason)
	return result.Allowed, result.Reason, nil
}
Пример #3
0
func (r *REST) List(ctx kapi.Context, options *kapi.ListOptions) (runtime.Object, error) {
	userInfo, exists := kapi.UserFrom(ctx)
	if !exists {
		return nil, errors.New("a user must be provided")
	}

	// the caller might not have permission to run a subject access review (he has it by default, but it could have been removed).
	// So we'll escalate for the subject access review to determine rights
	accessReview := authorizationapi.AddUserToSAR(userInfo,
		&authorizationapi.SubjectAccessReview{
			Action: authorizationapi.Action{
				Verb:     "create",
				Group:    projectapi.GroupName,
				Resource: "projectrequests",
			},
		})
	accessReviewResponse, err := r.openshiftClient.SubjectAccessReviews().Create(accessReview)
	if err != nil {
		return nil, err
	}
	if accessReviewResponse.Allowed {
		return &unversioned.Status{Status: unversioned.StatusSuccess}, nil
	}

	forbiddenError := kapierror.NewForbidden(projectapi.Resource("projectrequest"), "", errors.New("you may not request a new project via this API."))
	if len(r.message) > 0 {
		forbiddenError.ErrStatus.Message = r.message
		forbiddenError.ErrStatus.Details = &unversioned.StatusDetails{
			Kind: "ProjectRequest",
			Causes: []unversioned.StatusCause{
				{Message: r.message},
			},
		}
	} else {
		forbiddenError.ErrStatus.Message = "You may not request a new project via this API."
	}
	return nil, forbiddenError
}