// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { resourceAccessReview, ok := obj.(*authorizationapi.ResourceAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a resourceAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateResourceAccessReview(resourceAccessReview); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(resourceAccessReview.Kind), "", errs) } // if a namespace is present on the request, then the namespace on the on the RAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an RAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { resourceAccessReview.Action.Namespace = namespace } else if err := r.isAllowed(ctx, resourceAccessReview); err != nil { // this check is mutually exclusive to the condition above. localSAR and localRAR both clear the namespace before delegating their calls // We only need to check if the RAR is allowed **again** if the authorizer didn't already approve the request for a legacy call. return nil, err } requestContext := kapi.WithNamespace(ctx, resourceAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(resourceAccessReview.Action) users, groups, err := r.authorizer.GetAllowedSubjects(requestContext, attributes) response := &authorizationapi.ResourceAccessReviewResponse{ Namespace: resourceAccessReview.Action.Namespace, Users: users, Groups: groups, } if err != nil { response.EvaluationError = err.Error() } return response, nil }
// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { resourceAccessReview, ok := obj.(*authorizationapi.ResourceAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a resourceAccessReview: %#v", obj)) } if err := kutilerrors.NewAggregate(authorizationvalidation.ValidateResourceAccessReview(resourceAccessReview)); err != nil { return nil, err } // if a namespace is present on the request, then the namespace on the on the RAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an RAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { resourceAccessReview.Action.Namespace = namespace } if err := r.isAllowed(ctx, resourceAccessReview); err != nil { return nil, err } requestContext := kapi.WithNamespace(ctx, resourceAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(resourceAccessReview.Action) users, groups, err := r.authorizer.GetAllowedSubjects(requestContext, attributes) if err != nil { return nil, err } response := &authorizationapi.ResourceAccessReviewResponse{ Namespace: resourceAccessReview.Action.Namespace, Users: users, Groups: groups, } return response, nil }
func (r *subjectAccessTest) runTest(t *testing.T) { storage := NewREST(subjectaccessreview.NewRegistry(subjectaccessreview.NewREST(r.authorizer))) expectedResponse := &authorizationapi.SubjectAccessReviewResponse{ Namespace: r.reviewRequest.Action.Namespace, Allowed: r.authorizer.allowed, Reason: r.authorizer.reason, } expectedAttributes := authorizer.ToDefaultAuthorizationAttributes(r.reviewRequest.Action) ctx := kapi.WithNamespace(kapi.NewContext(), r.reviewRequest.Action.Namespace) if r.requestingUser != nil { ctx = kapi.WithUser(ctx, r.requestingUser) } obj, err := storage.Create(ctx, r.reviewRequest) if err != nil && len(r.authorizer.err) == 0 { t.Fatalf("unexpected error: %v", err) } if len(r.authorizer.err) != 0 { if err == nil { t.Fatalf("unexpected non-error: %v", err) } if e, a := r.authorizer.err, err.Error(); e != a { t.Fatalf("expected %v, got %v", e, a) } return } switch obj.(type) { case *authorizationapi.SubjectAccessReviewResponse: if !reflect.DeepEqual(expectedResponse, obj) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(expectedResponse, obj)) } case nil: if len(r.authorizer.err) == 0 { t.Fatal("unexpected nil object") } default: t.Errorf("Unexpected obj type: %v", obj) } if !reflect.DeepEqual(expectedAttributes, r.authorizer.actualAttributes) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(expectedAttributes, r.authorizer.actualAttributes)) } if !reflect.DeepEqual(r.expectedUserInfo, r.authorizer.actualUserInfo) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(r.expectedUserInfo, r.authorizer.actualUserInfo)) } }
// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a subjectAccessReview: %#v", obj)) } if err := kutilerrors.NewAggregate(authorizationvalidation.ValidateSubjectAccessReview(subjectAccessReview)); err != nil { return nil, err } // if a namespace is present on the request, then the namespace on the on the SAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an SAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { subjectAccessReview.Action.Namespace = namespace } else if err := r.isAllowed(ctx, subjectAccessReview); err != nil { // this check is mutually exclusive to the condition above. localSAR and localRAR both clear the namespace before delegating their calls // We only need to check if the SAR is allowed **again** if the authorizer didn't already approve the request for a legacy call. return nil, err } var userToCheck user.Info if (len(subjectAccessReview.User) == 0) && (len(subjectAccessReview.Groups) == 0) { // if no user or group was specified, use the info from the context ctxUser, exists := kapi.UserFrom(ctx) if !exists { return nil, kapierrors.NewBadRequest("user missing from context") } userToCheck = ctxUser } else { userToCheck = &user.DefaultInfo{ Name: subjectAccessReview.User, Groups: subjectAccessReview.Groups.List(), } } requestContext := kapi.WithNamespace(kapi.WithUser(ctx, userToCheck), subjectAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(subjectAccessReview.Action) allowed, reason, err := r.authorizer.Authorize(requestContext, attributes) if err != nil { return nil, err } response := &authorizationapi.SubjectAccessReviewResponse{ Namespace: subjectAccessReview.Action.Namespace, Allowed: allowed, Reason: reason, } return response, nil }
func (r *subjectAccessTest) runTest(t *testing.T) { storage := REST{r.authorizer} expectedResponse := &authorizationapi.SubjectAccessReviewResponse{ Namespace: r.reviewRequest.Action.Namespace, Allowed: r.authorizer.allowed, Reason: r.authorizer.reason, EvaluationError: r.authorizer.err, } expectedAttributes := authorizer.ToDefaultAuthorizationAttributes(r.reviewRequest.Action) ctx := kapi.WithNamespace(kapi.NewContext(), kapi.NamespaceAll) if r.requestingUser != nil { ctx = kapi.WithUser(ctx, r.requestingUser) } obj, err := storage.Create(ctx, r.reviewRequest) switch { case err == nil && len(r.expectedError) == 0: case err == nil && len(r.expectedError) != 0: t.Fatalf("missing expected error: %v", r.expectedError) case err != nil && len(r.expectedError) == 0: t.Fatalf("unexpected error: %v", err) case err != nil && len(r.expectedError) == 0 && err.Error() != r.expectedError: t.Fatalf("unexpected error: %v", r.expectedError) } if len(r.expectedError) > 0 { return } switch obj.(type) { case *authorizationapi.SubjectAccessReviewResponse: if !reflect.DeepEqual(expectedResponse, obj) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(expectedResponse, obj)) } default: t.Errorf("Unexpected obj type: %v", obj) } if !reflect.DeepEqual(expectedAttributes, r.authorizer.actualAttributes) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(expectedAttributes, r.authorizer.actualAttributes)) } if !reflect.DeepEqual(r.expectedUserInfo, r.authorizer.actualUserInfo) { t.Errorf("diff %v", diff.ObjectGoPrintDiff(r.expectedUserInfo, r.authorizer.actualUserInfo)) } }
func (r *resourceAccessTest) runTest(t *testing.T) { storage := NewREST(resourceaccessreview.NewRegistry(resourceaccessreview.NewREST(r.authorizer))) expectedResponse := &authorizationapi.ResourceAccessReviewResponse{ Namespace: r.reviewRequest.Action.Namespace, Users: r.authorizer.users, Groups: r.authorizer.groups, } expectedAttributes := authorizer.ToDefaultAuthorizationAttributes(r.reviewRequest.Action) ctx := kapi.WithNamespace(kapi.NewContext(), r.reviewRequest.Action.Namespace) obj, err := storage.Create(ctx, r.reviewRequest) if err != nil && len(r.authorizer.err) == 0 { t.Fatalf("unexpected error: %v", err) } if len(r.authorizer.err) != 0 { if err == nil { t.Fatalf("unexpected non-error: %v", err) } if e, a := r.authorizer.err, err.Error(); e != a { t.Fatalf("expected %v, got %v", e, a) } return } switch obj.(type) { case *authorizationapi.ResourceAccessReviewResponse: if !reflect.DeepEqual(expectedResponse, obj) { t.Errorf("diff %v", util.ObjectGoPrintDiff(expectedResponse, obj)) } case nil: if len(r.authorizer.err) == 0 { t.Fatal("unexpected nil object") } default: t.Errorf("Unexpected obj type: %v", obj) } if !reflect.DeepEqual(expectedAttributes, r.authorizer.actualAttributes) { t.Errorf("diff %v", util.ObjectGoPrintDiff(expectedAttributes, r.authorizer.actualAttributes)) } }
// Create registers a given new ResourceAccessReview instance to r.registry. func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { subjectAccessReview, ok := obj.(*authorizationapi.SubjectAccessReview) if !ok { return nil, kapierrors.NewBadRequest(fmt.Sprintf("not a subjectAccessReview: %#v", obj)) } if errs := authorizationvalidation.ValidateSubjectAccessReview(subjectAccessReview); len(errs) > 0 { return nil, kapierrors.NewInvalid(authorizationapi.Kind(subjectAccessReview.Kind), "", errs) } // if a namespace is present on the request, then the namespace on the on the SAR is overwritten. // This is to support backwards compatibility. To have gotten here in this state, it means that // the authorizer decided that a user could run an SAR against this namespace if namespace := kapi.NamespaceValue(ctx); len(namespace) > 0 { subjectAccessReview.Action.Namespace = namespace } else if err := r.isAllowed(ctx, subjectAccessReview); err != nil { // this check is mutually exclusive to the condition above. localSAR and localRAR both clear the namespace before delegating their calls // We only need to check if the SAR is allowed **again** if the authorizer didn't already approve the request for a legacy call. return nil, err } var userToCheck *user.DefaultInfo if (len(subjectAccessReview.User) == 0) && (len(subjectAccessReview.Groups) == 0) { // if no user or group was specified, use the info from the context ctxUser, exists := kapi.UserFrom(ctx) if !exists { return nil, kapierrors.NewBadRequest("user missing from context") } // make a copy, we don't want to risk changing the original newExtra := map[string][]string{} for k, v := range ctxUser.GetExtra() { if v == nil { newExtra[k] = nil continue } newSlice := make([]string, len(v), len(v)) copy(newSlice, v) newExtra[k] = newSlice } userToCheck = &user.DefaultInfo{ Name: ctxUser.GetName(), Groups: ctxUser.GetGroups(), UID: ctxUser.GetUID(), Extra: newExtra, } } else { userToCheck = &user.DefaultInfo{ Name: subjectAccessReview.User, Groups: subjectAccessReview.Groups.List(), Extra: map[string][]string{}, } } switch { case subjectAccessReview.Scopes == nil: // leave the scopes alone. on a self-sar, this means "use incoming request", on regular-sar it means, "use no scope restrictions" case len(subjectAccessReview.Scopes) == 0: // this always means "use no scope restrictions", so delete them delete(userToCheck.Extra, authorizationapi.ScopesKey) case len(subjectAccessReview.Scopes) > 0: // this always means, "use these scope restrictions", so force the value userToCheck.Extra[authorizationapi.ScopesKey] = subjectAccessReview.Scopes } requestContext := kapi.WithNamespace(kapi.WithUser(ctx, userToCheck), subjectAccessReview.Action.Namespace) attributes := authorizer.ToDefaultAuthorizationAttributes(subjectAccessReview.Action) allowed, reason, err := r.authorizer.Authorize(requestContext, attributes) if err != nil { return nil, err } response := &authorizationapi.SubjectAccessReviewResponse{ Namespace: subjectAccessReview.Action.Namespace, Allowed: allowed, Reason: reason, } return response, nil }