...

Source file src/k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview/rest_test.go

Documentation: k8s.io/kubernetes/pkg/registry/authorization/subjectaccessreview

     1  /*
     2  Copyright 2017 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package subjectaccessreview
    18  
    19  import (
    20  	"context"
    21  	"errors"
    22  	"reflect"
    23  	"strings"
    24  	"testing"
    25  
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apiserver/pkg/authentication/user"
    28  	"k8s.io/apiserver/pkg/authorization/authorizer"
    29  	genericapirequest "k8s.io/apiserver/pkg/endpoints/request"
    30  	"k8s.io/apiserver/pkg/registry/rest"
    31  	authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
    32  )
    33  
    34  type fakeAuthorizer struct {
    35  	attrs authorizer.Attributes
    36  
    37  	decision authorizer.Decision
    38  	reason   string
    39  	err      error
    40  }
    41  
    42  func (f *fakeAuthorizer) Authorize(ctx context.Context, attrs authorizer.Attributes) (authorizer.Decision, string, error) {
    43  	f.attrs = attrs
    44  	return f.decision, f.reason, f.err
    45  }
    46  
    47  func TestCreate(t *testing.T) {
    48  	testcases := map[string]struct {
    49  		spec     authorizationapi.SubjectAccessReviewSpec
    50  		decision authorizer.Decision
    51  		reason   string
    52  		err      error
    53  
    54  		expectedErr    string
    55  		expectedAttrs  authorizer.Attributes
    56  		expectedStatus authorizationapi.SubjectAccessReviewStatus
    57  	}{
    58  		"empty": {
    59  			expectedErr: "nonResourceAttributes or resourceAttributes",
    60  		},
    61  
    62  		"nonresource rejected": {
    63  			spec: authorizationapi.SubjectAccessReviewSpec{
    64  				User:                  "bob",
    65  				NonResourceAttributes: &authorizationapi.NonResourceAttributes{Verb: "get", Path: "/mypath"},
    66  			},
    67  			decision: authorizer.DecisionNoOpinion,
    68  			reason:   "myreason",
    69  			err:      errors.New("myerror"),
    70  			expectedAttrs: authorizer.AttributesRecord{
    71  				User:            &user.DefaultInfo{Name: "bob"},
    72  				Verb:            "get",
    73  				Path:            "/mypath",
    74  				ResourceRequest: false,
    75  			},
    76  			expectedStatus: authorizationapi.SubjectAccessReviewStatus{
    77  				Allowed:         false,
    78  				Reason:          "myreason",
    79  				EvaluationError: "myerror",
    80  			},
    81  		},
    82  
    83  		"nonresource allowed": {
    84  			spec: authorizationapi.SubjectAccessReviewSpec{
    85  				User:                  "bob",
    86  				NonResourceAttributes: &authorizationapi.NonResourceAttributes{Verb: "get", Path: "/mypath"},
    87  			},
    88  			decision: authorizer.DecisionAllow,
    89  			reason:   "allowed",
    90  			err:      nil,
    91  			expectedAttrs: authorizer.AttributesRecord{
    92  				User:            &user.DefaultInfo{Name: "bob"},
    93  				Verb:            "get",
    94  				Path:            "/mypath",
    95  				ResourceRequest: false,
    96  			},
    97  			expectedStatus: authorizationapi.SubjectAccessReviewStatus{
    98  				Allowed:         true,
    99  				Reason:          "allowed",
   100  				EvaluationError: "",
   101  			},
   102  		},
   103  
   104  		"resource rejected": {
   105  			spec: authorizationapi.SubjectAccessReviewSpec{
   106  				User: "bob",
   107  				ResourceAttributes: &authorizationapi.ResourceAttributes{
   108  					Namespace:   "myns",
   109  					Verb:        "create",
   110  					Group:       "extensions",
   111  					Version:     "v1beta1",
   112  					Resource:    "deployments",
   113  					Subresource: "scale",
   114  					Name:        "mydeployment",
   115  				},
   116  			},
   117  			decision: authorizer.DecisionNoOpinion,
   118  			reason:   "myreason",
   119  			err:      errors.New("myerror"),
   120  			expectedAttrs: authorizer.AttributesRecord{
   121  				User:            &user.DefaultInfo{Name: "bob"},
   122  				Namespace:       "myns",
   123  				Verb:            "create",
   124  				APIGroup:        "extensions",
   125  				APIVersion:      "v1beta1",
   126  				Resource:        "deployments",
   127  				Subresource:     "scale",
   128  				Name:            "mydeployment",
   129  				ResourceRequest: true,
   130  			},
   131  			expectedStatus: authorizationapi.SubjectAccessReviewStatus{
   132  				Allowed:         false,
   133  				Denied:          false,
   134  				Reason:          "myreason",
   135  				EvaluationError: "myerror",
   136  			},
   137  		},
   138  
   139  		"resource allowed": {
   140  			spec: authorizationapi.SubjectAccessReviewSpec{
   141  				User: "bob",
   142  				ResourceAttributes: &authorizationapi.ResourceAttributes{
   143  					Namespace:   "myns",
   144  					Verb:        "create",
   145  					Group:       "extensions",
   146  					Version:     "v1beta1",
   147  					Resource:    "deployments",
   148  					Subresource: "scale",
   149  					Name:        "mydeployment",
   150  				},
   151  			},
   152  			decision: authorizer.DecisionAllow,
   153  			reason:   "allowed",
   154  			err:      nil,
   155  			expectedAttrs: authorizer.AttributesRecord{
   156  				User:            &user.DefaultInfo{Name: "bob"},
   157  				Namespace:       "myns",
   158  				Verb:            "create",
   159  				APIGroup:        "extensions",
   160  				APIVersion:      "v1beta1",
   161  				Resource:        "deployments",
   162  				Subresource:     "scale",
   163  				Name:            "mydeployment",
   164  				ResourceRequest: true,
   165  			},
   166  			expectedStatus: authorizationapi.SubjectAccessReviewStatus{
   167  				Allowed:         true,
   168  				Denied:          false,
   169  				Reason:          "allowed",
   170  				EvaluationError: "",
   171  			},
   172  		},
   173  
   174  		"resource denied": {
   175  			spec: authorizationapi.SubjectAccessReviewSpec{
   176  				User:               "bob",
   177  				ResourceAttributes: &authorizationapi.ResourceAttributes{},
   178  			},
   179  			decision: authorizer.DecisionDeny,
   180  			expectedAttrs: authorizer.AttributesRecord{
   181  				User:            &user.DefaultInfo{Name: "bob"},
   182  				ResourceRequest: true,
   183  				APIVersion:      "*",
   184  			},
   185  			expectedStatus: authorizationapi.SubjectAccessReviewStatus{
   186  				Allowed: false,
   187  				Denied:  true,
   188  			},
   189  		},
   190  	}
   191  
   192  	for k, tc := range testcases {
   193  		auth := &fakeAuthorizer{
   194  			decision: tc.decision,
   195  			reason:   tc.reason,
   196  			err:      tc.err,
   197  		}
   198  		storage := NewREST(auth)
   199  
   200  		result, err := storage.Create(genericapirequest.NewContext(), &authorizationapi.SubjectAccessReview{Spec: tc.spec}, rest.ValidateAllObjectFunc, &metav1.CreateOptions{})
   201  		if err != nil {
   202  			if tc.expectedErr != "" {
   203  				if !strings.Contains(err.Error(), tc.expectedErr) {
   204  					t.Errorf("%s: expected %s to contain %q", k, err, tc.expectedErr)
   205  				}
   206  			} else {
   207  				t.Errorf("%s: %v", k, err)
   208  			}
   209  			continue
   210  		}
   211  		if !reflect.DeepEqual(auth.attrs, tc.expectedAttrs) {
   212  			t.Errorf("%s: expected\n%#v\ngot\n%#v", k, tc.expectedAttrs, auth.attrs)
   213  		}
   214  		status := result.(*authorizationapi.SubjectAccessReview).Status
   215  		if !reflect.DeepEqual(status, tc.expectedStatus) {
   216  			t.Errorf("%s: expected\n%#v\ngot\n%#v", k, tc.expectedStatus, status)
   217  		}
   218  	}
   219  }
   220  

View as plain text