1/* 2Copyright 2018 The Kubernetes Authors. 3 4Licensed under the Apache License, Version 2.0 (the "License"); 5you may not use this file except in compliance with the License. 6You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10Unless required by applicable law or agreed to in writing, software 11distributed under the License is distributed on an "AS IS" BASIS, 12WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13See the License for the specific language governing permissions and 14limitations under the License. 15*/ 16 17package authenticator 18 19import ( 20 "context" 21 "errors" 22 "fmt" 23 "reflect" 24 "testing" 25 26 "k8s.io/apimachinery/pkg/util/diff" 27 "k8s.io/apiserver/pkg/authentication/user" 28) 29 30func TestAuthenticate(t *testing.T) { 31 type treq struct { 32 resp *Response 33 authenticated bool 34 err error 35 36 wantResp *Response 37 wantAuthenticated bool 38 wantErr bool 39 } 40 type taudcfg struct { 41 auds Audiences 42 implicitAuds Audiences 43 } 44 cs := []struct { 45 name string 46 47 taudcfgs []taudcfg 48 treqs []treq 49 }{ 50 { 51 name: "good audience", 52 53 taudcfgs: []taudcfg{ 54 { 55 implicitAuds: Audiences{"api"}, 56 auds: Audiences{"api"}, 57 }, 58 { 59 implicitAuds: Audiences{"api", "other"}, 60 auds: Audiences{"api"}, 61 }, 62 { 63 implicitAuds: Audiences{"api"}, 64 auds: Audiences{"api", "other"}, 65 }, 66 { 67 implicitAuds: Audiences{"api", "other"}, 68 auds: Audiences{"api", "other_other"}, 69 }, 70 }, 71 72 treqs: []treq{ 73 { 74 resp: &Response{ 75 User: &user.DefaultInfo{ 76 Name: "test_user", 77 }, 78 }, 79 authenticated: true, 80 81 wantResp: &Response{ 82 User: &user.DefaultInfo{ 83 Name: "test_user", 84 }, 85 Audiences: Audiences{"api"}, 86 }, 87 wantAuthenticated: true, 88 }, 89 { 90 err: errors.New("uhoh"), 91 wantErr: true, 92 }, 93 { 94 authenticated: false, 95 wantAuthenticated: false, 96 }, 97 }, 98 }, 99 { 100 name: "multiple good audiences", 101 102 taudcfgs: []taudcfg{ 103 { 104 implicitAuds: Audiences{"api", "other_api"}, 105 auds: Audiences{"api", "other_api"}, 106 }, 107 { 108 implicitAuds: Audiences{"api", "other_api", "other"}, 109 auds: Audiences{"api", "other_api"}, 110 }, 111 { 112 implicitAuds: Audiences{"api", "other_api"}, 113 auds: Audiences{"api", "other_api", "other"}, 114 }, 115 { 116 implicitAuds: Audiences{"api", "other_api", "other"}, 117 auds: Audiences{"api", "other_api", "other_other"}, 118 }, 119 }, 120 121 treqs: []treq{ 122 { 123 resp: &Response{ 124 User: &user.DefaultInfo{ 125 Name: "test_user", 126 }, 127 }, 128 authenticated: true, 129 130 wantResp: &Response{ 131 User: &user.DefaultInfo{ 132 Name: "test_user", 133 }, 134 Audiences: Audiences{"api", "other_api"}, 135 }, 136 wantAuthenticated: true, 137 }, 138 { 139 err: errors.New("uhoh"), 140 141 wantErr: true, 142 }, 143 { 144 authenticated: false, 145 146 wantAuthenticated: false, 147 }, 148 }, 149 }, 150 { 151 name: "bad audience(s)", 152 153 taudcfgs: []taudcfg{ 154 { 155 implicitAuds: Audiences{"api"}, 156 auds: Audiences{"other_api"}, 157 }, 158 { 159 implicitAuds: Audiences{}, 160 auds: Audiences{"other_api"}, 161 }, 162 { 163 implicitAuds: Audiences{"api"}, 164 auds: Audiences{}, 165 }, 166 { 167 implicitAuds: Audiences{"api", "other"}, 168 auds: Audiences{}, 169 }, 170 { 171 implicitAuds: Audiences{}, 172 auds: Audiences{"api", "other"}, 173 }, 174 }, 175 176 treqs: []treq{ 177 { 178 resp: &Response{ 179 User: &user.DefaultInfo{ 180 Name: "test_user", 181 }, 182 }, 183 authenticated: true, 184 185 wantAuthenticated: false, 186 }, 187 { 188 err: errors.New("uhoh"), 189 190 wantAuthenticated: false, 191 }, 192 { 193 authenticated: false, 194 195 wantAuthenticated: false, 196 }, 197 }, 198 }, 199 } 200 201 for _, c := range cs { 202 t.Run(c.name, func(t *testing.T) { 203 for _, taudcfg := range c.taudcfgs { 204 for _, treq := range c.treqs { 205 t.Run(fmt.Sprintf("auds=%q,implicit=%q", taudcfg.auds, taudcfg.implicitAuds), func(t *testing.T) { 206 ctx := context.Background() 207 ctx = WithAudiences(ctx, taudcfg.auds) 208 resp, ok, err := authenticate(ctx, taudcfg.implicitAuds, func() (*Response, bool, error) { 209 if treq.resp != nil { 210 resp := *treq.resp 211 return &resp, treq.authenticated, treq.err 212 } 213 return nil, treq.authenticated, treq.err 214 }) 215 if got, want := (err != nil), treq.wantErr; got != want { 216 t.Errorf("Unexpected error. got=%v, want=%v, err=%v", got, want, err) 217 } 218 if got, want := ok, treq.wantAuthenticated; got != want { 219 t.Errorf("Unexpected authentication. got=%v, want=%v", got, want) 220 } 221 if got, want := resp, treq.wantResp; !reflect.DeepEqual(got, want) { 222 t.Errorf("Unexpected response. diff:\n%v", diff.ObjectGoPrintDiff(got, want)) 223 } 224 }) 225 } 226 } 227 }) 228 } 229} 230