k8s.io/apiserver@v0.31.1/pkg/authentication/request/bearertoken/bearertoken_test.go (about) 1 /* 2 Copyright 2014 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 bearertoken 18 19 import ( 20 "context" 21 "errors" 22 "net/http" 23 "reflect" 24 "testing" 25 26 "k8s.io/apiserver/pkg/authentication/authenticator" 27 "k8s.io/apiserver/pkg/authentication/user" 28 genericapirequest "k8s.io/apiserver/pkg/endpoints/request" 29 "k8s.io/apiserver/pkg/warning" 30 ) 31 32 func TestAuthenticateRequest(t *testing.T) { 33 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 34 if token != "token" { 35 t.Errorf("unexpected token: %s", token) 36 } 37 return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil 38 })) 39 resp, ok, err := auth.AuthenticateRequest(&http.Request{ 40 Header: http.Header{"Authorization": []string{"Bearer token"}}, 41 }) 42 if !ok || resp == nil || err != nil { 43 t.Errorf("expected valid user") 44 } 45 } 46 47 func TestAuthenticateRequestIncludingValueAfterToken(t *testing.T) { 48 testCases := []struct { 49 Req *http.Request 50 }{ 51 {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer token a"}}}}, 52 {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer token a b c"}}}}, 53 {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer token a"}}}}, 54 } 55 for i, testCase := range testCases { 56 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 57 if token != "token" { 58 t.Errorf("unexpected token: %s", token) 59 } 60 return &authenticator.Response{User: &user.DefaultInfo{Name: "user"}}, true, nil 61 })) 62 resp, ok, err := auth.AuthenticateRequest(testCase.Req) 63 if !ok || resp == nil || err != nil { 64 t.Errorf("%d: expected valid user", i) 65 } 66 } 67 } 68 69 func TestAuthenticateRequestTokenInvalid(t *testing.T) { 70 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 71 return nil, false, nil 72 })) 73 resp, ok, err := auth.AuthenticateRequest(&http.Request{ 74 Header: http.Header{"Authorization": []string{"Bearer token"}}, 75 }) 76 if ok || resp != nil { 77 t.Errorf("expected not authenticated user") 78 } 79 if err != invalidToken { 80 t.Errorf("expected invalidToken error, got %v", err) 81 } 82 } 83 84 func TestAuthenticateRequestTokenInvalidCustomError(t *testing.T) { 85 customError := errors.New("custom") 86 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 87 return nil, false, customError 88 })) 89 resp, ok, err := auth.AuthenticateRequest(&http.Request{ 90 Header: http.Header{"Authorization": []string{"Bearer token"}}, 91 }) 92 if ok || resp != nil { 93 t.Errorf("expected not authenticated user") 94 } 95 if err != customError { 96 t.Errorf("expected custom error, got %v", err) 97 } 98 } 99 100 func TestAuthenticateRequestTokenError(t *testing.T) { 101 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 102 return nil, false, errors.New("error") 103 })) 104 resp, ok, err := auth.AuthenticateRequest(&http.Request{ 105 Header: http.Header{"Authorization": []string{"Bearer token"}}, 106 }) 107 if ok || resp != nil || err == nil { 108 t.Errorf("expected error") 109 } 110 } 111 112 func TestAuthenticateRequestBadValue(t *testing.T) { 113 testCases := []struct { 114 Req *http.Request 115 }{ 116 {Req: &http.Request{}}, 117 {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer"}}}}, 118 {Req: &http.Request{Header: http.Header{"Authorization": []string{"bear token"}}}}, 119 {Req: &http.Request{Header: http.Header{"Authorization": []string{"Bearer: token"}}}}, 120 } 121 for i, testCase := range testCases { 122 auth := New(authenticator.TokenFunc(func(ctx context.Context, token string) (*authenticator.Response, bool, error) { 123 t.Errorf("authentication should not have been called") 124 return nil, false, nil 125 })) 126 user, ok, err := auth.AuthenticateRequest(testCase.Req) 127 if ok || user != nil || err != nil { 128 t.Errorf("%d: expected not authenticated (no token)", i) 129 } 130 } 131 } 132 133 type dummyRecorder struct { 134 agent string 135 text string 136 } 137 138 func (r *dummyRecorder) AddWarning(agent, text string) { 139 r.agent = agent 140 r.text = text 141 return 142 } 143 144 func (r *dummyRecorder) getWarning() string { 145 return r.text 146 } 147 148 var _ warning.Recorder = &dummyRecorder{} 149 150 func TestBearerToken(t *testing.T) { 151 tests := map[string]struct { 152 AuthorizationHeaders []string 153 TokenAuth authenticator.Token 154 155 ExpectedUserName string 156 ExpectedOK bool 157 ExpectedErr bool 158 ExpectedAuthorizationHeaders []string 159 ExpectedRecordedWarning string 160 }{ 161 "no header": { 162 AuthorizationHeaders: nil, 163 ExpectedUserName: "", 164 ExpectedOK: false, 165 ExpectedErr: false, 166 ExpectedAuthorizationHeaders: nil, 167 }, 168 "empty header": { 169 AuthorizationHeaders: []string{""}, 170 ExpectedUserName: "", 171 ExpectedOK: false, 172 ExpectedErr: false, 173 ExpectedAuthorizationHeaders: []string{""}, 174 }, 175 "non-bearer header": { 176 AuthorizationHeaders: []string{"Basic 123"}, 177 ExpectedUserName: "", 178 ExpectedOK: false, 179 ExpectedErr: false, 180 ExpectedAuthorizationHeaders: []string{"Basic 123"}, 181 }, 182 "empty bearer token": { 183 AuthorizationHeaders: []string{"Bearer "}, 184 ExpectedUserName: "", 185 ExpectedOK: false, 186 ExpectedErr: false, 187 ExpectedAuthorizationHeaders: []string{"Bearer "}, 188 }, 189 "valid bearer token removing header": { 190 AuthorizationHeaders: []string{"Bearer 123"}, 191 TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { 192 return &authenticator.Response{User: &user.DefaultInfo{Name: "myuser"}}, true, nil 193 }), 194 ExpectedUserName: "myuser", 195 ExpectedOK: true, 196 ExpectedErr: false, 197 ExpectedAuthorizationHeaders: nil, 198 }, 199 "invalid bearer token": { 200 AuthorizationHeaders: []string{"Bearer 123"}, 201 TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { return nil, false, nil }), 202 ExpectedUserName: "", 203 ExpectedOK: false, 204 ExpectedErr: true, 205 ExpectedAuthorizationHeaders: []string{"Bearer 123"}, 206 }, 207 "valid bearer token with a space": { 208 AuthorizationHeaders: []string{"Bearer token"}, 209 ExpectedUserName: "", 210 ExpectedOK: false, 211 ExpectedErr: false, 212 ExpectedAuthorizationHeaders: []string{"Bearer token"}, 213 ExpectedRecordedWarning: invalidTokenWithSpaceWarning, 214 }, 215 "error bearer token": { 216 AuthorizationHeaders: []string{"Bearer 123"}, 217 TokenAuth: authenticator.TokenFunc(func(ctx context.Context, t string) (*authenticator.Response, bool, error) { 218 return nil, false, errors.New("error") 219 }), 220 ExpectedUserName: "", 221 ExpectedOK: false, 222 ExpectedErr: true, 223 ExpectedAuthorizationHeaders: []string{"Bearer 123"}, 224 }, 225 } 226 227 for k, tc := range tests { 228 dc := dummyRecorder{agent: "", text: ""} 229 ctx := genericapirequest.NewDefaultContext() 230 ctxWithRecorder := warning.WithWarningRecorder(ctx, &dc) 231 req, _ := http.NewRequestWithContext(ctxWithRecorder, "GET", "/", nil) 232 for _, h := range tc.AuthorizationHeaders { 233 req.Header.Add("Authorization", h) 234 } 235 236 bearerAuth := New(tc.TokenAuth) 237 resp, ok, err := bearerAuth.AuthenticateRequest(req) 238 if tc.ExpectedErr != (err != nil) { 239 t.Errorf("%s: Expected err=%v, got %v", k, tc.ExpectedErr, err) 240 continue 241 } 242 if ok != tc.ExpectedOK { 243 t.Errorf("%s: Expected ok=%v, got %v", k, tc.ExpectedOK, ok) 244 continue 245 } 246 if ok && resp.User.GetName() != tc.ExpectedUserName { 247 t.Errorf("%s: Expected username=%v, got %v", k, tc.ExpectedUserName, resp.User.GetName()) 248 continue 249 } 250 if len(tc.ExpectedRecordedWarning) > 0 && tc.ExpectedRecordedWarning != dc.getWarning() { 251 t.Errorf("%s: Expected recorded warning=%v, got %v", k, tc.ExpectedRecordedWarning, dc.getWarning()) 252 continue 253 } 254 if !reflect.DeepEqual(req.Header["Authorization"], tc.ExpectedAuthorizationHeaders) { 255 t.Errorf("%s: Expected headers=%#v, got %#v", k, tc.ExpectedAuthorizationHeaders, req.Header["Authorization"]) 256 continue 257 } 258 } 259 }