k8s.io/kubernetes@v1.29.3/pkg/auth/authorizer/abac/abac_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 abac 18 19 import ( 20 "context" 21 "io/ioutil" 22 "os" 23 "reflect" 24 "testing" 25 26 "k8s.io/apimachinery/pkg/runtime" 27 "k8s.io/apiserver/pkg/authentication/user" 28 "k8s.io/apiserver/pkg/authorization/authorizer" 29 "k8s.io/kubernetes/pkg/apis/abac" 30 "k8s.io/kubernetes/pkg/apis/abac/v0" 31 "k8s.io/kubernetes/pkg/apis/abac/v1beta1" 32 ) 33 34 func TestEmptyFile(t *testing.T) { 35 _, err := newWithContents(t, "") 36 if err != nil { 37 t.Errorf("unable to read policy file: %v", err) 38 } 39 } 40 41 func TestOneLineFileNoNewLine(t *testing.T) { 42 _, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods", "namespace":"ns1"}`) 43 if err != nil { 44 t.Errorf("unable to read policy file: %v", err) 45 } 46 } 47 48 func TestTwoLineFile(t *testing.T) { 49 _, err := newWithContents(t, `{"user":"scheduler", "readonly": true, "resource": "pods"} 50 {"user":"scheduler", "readonly": true, "resource": "services"} 51 `) 52 if err != nil { 53 t.Errorf("unable to read policy file: %v", err) 54 } 55 } 56 57 // Test the file that we will point users at as an example. 58 func TestExampleFile(t *testing.T) { 59 _, err := NewFromFile("./example_policy_file.jsonl") 60 if err != nil { 61 t.Errorf("unable to read policy file: %v", err) 62 } 63 } 64 65 func TestAuthorizeV0(t *testing.T) { 66 a, err := newWithContents(t, `{ "readonly": true, "resource": "events" } 67 {"user":"scheduler", "readonly": true, "resource": "pods" } 68 {"user":"scheduler", "resource": "bindings" } 69 {"user":"kubelet", "readonly": true, "resource": "bindings" } 70 {"user":"kubelet", "resource": "events" } 71 {"user":"alice", "namespace": "projectCaribou"} 72 {"user":"bob", "readonly": true, "namespace": "projectCaribou"} 73 `) 74 if err != nil { 75 t.Fatalf("unable to read policy file: %v", err) 76 } 77 78 authenticatedGroup := []string{user.AllAuthenticated} 79 80 uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup} 81 uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup} 82 uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup} 83 84 testCases := []struct { 85 User user.DefaultInfo 86 Verb string 87 Resource string 88 NS string 89 APIGroup string 90 Path string 91 ExpectDecision authorizer.Decision 92 }{ 93 // Scheduler can read pods 94 {User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 95 {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow}, 96 // Scheduler cannot write pods 97 {User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 98 {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 99 // Scheduler can write bindings 100 {User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 101 {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow}, 102 103 // Alice can read and write anything in the right namespace. 104 {User: uAlice, Verb: "get", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 105 {User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 106 {User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 107 {User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 108 {User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 109 {User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 110 {User: uAlice, Verb: "update", Resource: "foo", NS: "projectCaribou", APIGroup: "bar", ExpectDecision: authorizer.DecisionAllow}, 111 // .. but not the wrong namespace. 112 {User: uAlice, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 113 {User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 114 {User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 115 116 // Chuck can read events, since anyone can. 117 {User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 118 {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow}, 119 // Chuck can't do other things. 120 {User: uChuck, Verb: "update", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 121 {User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 122 {User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 123 // Chunk can't access things with no kind or namespace 124 {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 125 } 126 for i, tc := range testCases { 127 attr := authorizer.AttributesRecord{ 128 User: &tc.User, 129 Verb: tc.Verb, 130 Resource: tc.Resource, 131 Namespace: tc.NS, 132 APIGroup: tc.APIGroup, 133 Path: tc.Path, 134 135 ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0, 136 } 137 decision, _, _ := a.Authorize(context.Background(), attr) 138 if tc.ExpectDecision != decision { 139 t.Logf("tc: %v -> attr %v", tc, attr) 140 t.Errorf("%d: Expected allowed=%v but actually allowed=%v\n\t%v", 141 i, tc.ExpectDecision, decision, tc) 142 } 143 } 144 } 145 146 func getResourceRules(infos []authorizer.ResourceRuleInfo) []authorizer.DefaultResourceRuleInfo { 147 rules := make([]authorizer.DefaultResourceRuleInfo, len(infos)) 148 for i, info := range infos { 149 rules[i] = authorizer.DefaultResourceRuleInfo{ 150 Verbs: info.GetVerbs(), 151 APIGroups: info.GetAPIGroups(), 152 Resources: info.GetResources(), 153 ResourceNames: info.GetResourceNames(), 154 } 155 } 156 return rules 157 } 158 159 func getNonResourceRules(infos []authorizer.NonResourceRuleInfo) []authorizer.DefaultNonResourceRuleInfo { 160 rules := make([]authorizer.DefaultNonResourceRuleInfo, len(infos)) 161 for i, info := range infos { 162 rules[i] = authorizer.DefaultNonResourceRuleInfo{ 163 Verbs: info.GetVerbs(), 164 NonResourceURLs: info.GetNonResourceURLs(), 165 } 166 } 167 return rules 168 } 169 170 func TestRulesFor(t *testing.T) { 171 a, err := newWithContents(t, ` 172 { "readonly": true, "resource": "events" } 173 {"user":"scheduler", "readonly": true, "resource": "pods" } 174 {"user":"scheduler", "resource": "bindings" } 175 {"user":"kubelet", "readonly": true, "resource": "pods" } 176 {"user":"kubelet", "resource": "events" } 177 {"user":"alice", "namespace": "projectCaribou"} 178 {"user":"bob", "readonly": true, "namespace": "projectCaribou"} 179 {"user":"bob", "readonly": true, "nonResourcePath": "*"} 180 {"group":"a", "resource": "bindings" } 181 {"group":"b", "readonly": true, "nonResourcePath": "*"} 182 `) 183 if err != nil { 184 t.Fatalf("unable to read policy file: %v", err) 185 } 186 187 authenticatedGroup := []string{user.AllAuthenticated} 188 189 uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup} 190 uKubelet := user.DefaultInfo{Name: "kubelet", UID: "uid2", Groups: []string{"a", "b"}} 191 uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup} 192 uBob := user.DefaultInfo{Name: "bob", UID: "uid4", Groups: authenticatedGroup} 193 uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: []string{"a", "b"}} 194 195 testCases := []struct { 196 User user.DefaultInfo 197 Namespace string 198 ExpectResourceRules []authorizer.DefaultResourceRuleInfo 199 ExpectNonResourceRules []authorizer.DefaultNonResourceRuleInfo 200 }{ 201 { 202 User: uScheduler, 203 Namespace: "ns1", 204 ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{ 205 { 206 Verbs: []string{"get", "list", "watch"}, 207 APIGroups: []string{"*"}, 208 Resources: []string{"events"}, 209 }, 210 { 211 Verbs: []string{"get", "list", "watch"}, 212 APIGroups: []string{"*"}, 213 Resources: []string{"pods"}, 214 }, 215 { 216 Verbs: []string{"*"}, 217 APIGroups: []string{"*"}, 218 Resources: []string{"bindings"}, 219 }, 220 }, 221 ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{}, 222 }, 223 { 224 User: uKubelet, 225 Namespace: "ns1", 226 ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{ 227 { 228 Verbs: []string{"get", "list", "watch"}, 229 APIGroups: []string{"*"}, 230 Resources: []string{"pods"}, 231 }, 232 { 233 Verbs: []string{"*"}, 234 APIGroups: []string{"*"}, 235 Resources: []string{"events"}, 236 }, 237 { 238 Verbs: []string{"*"}, 239 APIGroups: []string{"*"}, 240 Resources: []string{"bindings"}, 241 }, 242 { 243 Verbs: []string{"get", "list", "watch"}, 244 APIGroups: []string{"*"}, 245 Resources: []string{"*"}, 246 }, 247 }, 248 ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{ 249 { 250 Verbs: []string{"get", "list", "watch"}, 251 NonResourceURLs: []string{"*"}, 252 }, 253 }, 254 }, 255 { 256 User: uAlice, 257 Namespace: "projectCaribou", 258 ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{ 259 { 260 Verbs: []string{"get", "list", "watch"}, 261 APIGroups: []string{"*"}, 262 Resources: []string{"events"}, 263 }, 264 { 265 Verbs: []string{"*"}, 266 APIGroups: []string{"*"}, 267 Resources: []string{"*"}, 268 }, 269 }, 270 ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{}, 271 }, 272 { 273 User: uBob, 274 Namespace: "projectCaribou", 275 ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{ 276 { 277 Verbs: []string{"get", "list", "watch"}, 278 APIGroups: []string{"*"}, 279 Resources: []string{"events"}, 280 }, 281 { 282 Verbs: []string{"get", "list", "watch"}, 283 APIGroups: []string{"*"}, 284 Resources: []string{"*"}, 285 }, 286 { 287 Verbs: []string{"get", "list", "watch"}, 288 APIGroups: []string{"*"}, 289 Resources: []string{"*"}, 290 }, 291 }, 292 ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{ 293 { 294 Verbs: []string{"get", "list", "watch"}, 295 NonResourceURLs: []string{"*"}, 296 }, 297 }, 298 }, 299 { 300 User: uChuck, 301 Namespace: "ns1", 302 ExpectResourceRules: []authorizer.DefaultResourceRuleInfo{ 303 { 304 Verbs: []string{"*"}, 305 APIGroups: []string{"*"}, 306 Resources: []string{"bindings"}, 307 }, 308 { 309 Verbs: []string{"get", "list", "watch"}, 310 APIGroups: []string{"*"}, 311 Resources: []string{"*"}, 312 }, 313 }, 314 ExpectNonResourceRules: []authorizer.DefaultNonResourceRuleInfo{ 315 { 316 Verbs: []string{"get", "list", "watch"}, 317 NonResourceURLs: []string{"*"}, 318 }, 319 }, 320 }, 321 } 322 for i, tc := range testCases { 323 attr := authorizer.AttributesRecord{ 324 User: &tc.User, 325 Namespace: tc.Namespace, 326 } 327 resourceRules, nonResourceRules, _, _ := a.RulesFor(attr.GetUser(), attr.GetNamespace()) 328 actualResourceRules := getResourceRules(resourceRules) 329 if !reflect.DeepEqual(tc.ExpectResourceRules, actualResourceRules) { 330 t.Logf("tc: %v -> attr %v", tc, attr) 331 t.Errorf("%d: Expected: \n%#v\n but actual: \n%#v\n", 332 i, tc.ExpectResourceRules, actualResourceRules) 333 } 334 actualNonResourceRules := getNonResourceRules(nonResourceRules) 335 if !reflect.DeepEqual(tc.ExpectNonResourceRules, actualNonResourceRules) { 336 t.Logf("tc: %v -> attr %v", tc, attr) 337 t.Errorf("%d: Expected: \n%#v\n but actual: \n%#v\n", 338 i, tc.ExpectNonResourceRules, actualNonResourceRules) 339 } 340 } 341 } 342 343 func TestAuthorizeV1beta1(t *testing.T) { 344 a, err := newWithContents(t, 345 ` 346 # Comment line, after a blank line 347 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "nonResourcePath": "/api"}} 348 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/custom"}} 349 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "nonResourcePath": "/root/*"}} 350 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"noresource", "nonResourcePath": "*"}} 351 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"*", "readonly": true, "resource": "events", "namespace": "*"}} 352 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "readonly": true, "resource": "pods", "namespace": "*"}} 353 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"scheduler", "resource": "bindings", "namespace": "*"}} 354 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "readonly": true, "resource": "bindings", "namespace": "*"}} 355 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"kubelet", "resource": "events", "namespace": "*"}} 356 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"alice", "resource": "*", "namespace": "projectCaribou"}} 357 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"bob", "readonly": true, "resource": "*", "namespace": "projectCaribou"}} 358 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"debbie", "resource": "pods", "namespace": "projectCaribou"}} 359 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectAnyGroup", "apiGroup": "*"}} 360 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectEmptyGroup", "apiGroup": "" }} 361 {"apiVersion":"abac.authorization.kubernetes.io/v1beta1","kind":"Policy","spec":{"user":"apigroupuser", "resource": "*", "namespace": "projectXGroup", "apiGroup": "x"}}`) 362 363 if err != nil { 364 t.Fatalf("unable to read policy file: %v", err) 365 } 366 367 authenticatedGroup := []string{user.AllAuthenticated} 368 369 uScheduler := user.DefaultInfo{Name: "scheduler", UID: "uid1", Groups: authenticatedGroup} 370 uAlice := user.DefaultInfo{Name: "alice", UID: "uid3", Groups: authenticatedGroup} 371 uChuck := user.DefaultInfo{Name: "chuck", UID: "uid5", Groups: authenticatedGroup} 372 uDebbie := user.DefaultInfo{Name: "debbie", UID: "uid6", Groups: authenticatedGroup} 373 uNoResource := user.DefaultInfo{Name: "noresource", UID: "uid7", Groups: authenticatedGroup} 374 uAPIGroup := user.DefaultInfo{Name: "apigroupuser", UID: "uid8", Groups: authenticatedGroup} 375 376 testCases := []struct { 377 User user.DefaultInfo 378 Verb string 379 Resource string 380 APIGroup string 381 NS string 382 Path string 383 ExpectDecision authorizer.Decision 384 }{ 385 // Scheduler can read pods 386 {User: uScheduler, Verb: "list", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 387 {User: uScheduler, Verb: "list", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionAllow}, 388 // Scheduler cannot write pods 389 {User: uScheduler, Verb: "create", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 390 {User: uScheduler, Verb: "create", Resource: "pods", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 391 // Scheduler can write bindings 392 {User: uScheduler, Verb: "get", Resource: "bindings", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 393 {User: uScheduler, Verb: "get", Resource: "bindings", NS: "", ExpectDecision: authorizer.DecisionAllow}, 394 395 // Alice can read and write anything in the right namespace. 396 {User: uAlice, Verb: "get", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 397 {User: uAlice, Verb: "get", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 398 {User: uAlice, Verb: "get", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 399 {User: uAlice, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 400 {User: uAlice, Verb: "update", Resource: "widgets", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 401 {User: uAlice, Verb: "update", Resource: "", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 402 // .. but not the wrong namespace. 403 {User: uAlice, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 404 {User: uAlice, Verb: "get", Resource: "widgets", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 405 {User: uAlice, Verb: "get", Resource: "", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 406 407 // Debbie can write to pods in the right namespace 408 {User: uDebbie, Verb: "update", Resource: "pods", NS: "projectCaribou", ExpectDecision: authorizer.DecisionAllow}, 409 410 // Chuck can read events, since anyone can. 411 {User: uChuck, Verb: "get", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionAllow}, 412 {User: uChuck, Verb: "get", Resource: "events", NS: "", ExpectDecision: authorizer.DecisionAllow}, 413 // Chuck can't do other things. 414 {User: uChuck, Verb: "update", Resource: "events", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 415 {User: uChuck, Verb: "get", Resource: "pods", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 416 {User: uChuck, Verb: "get", Resource: "floop", NS: "ns1", ExpectDecision: authorizer.DecisionNoOpinion}, 417 // Chuck can't access things with no resource or namespace 418 {User: uChuck, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 419 // but can access /api 420 {User: uChuck, Verb: "get", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 421 // though he cannot write to it 422 {User: uChuck, Verb: "create", Path: "/api", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 423 // while he can write to /custom 424 {User: uChuck, Verb: "update", Path: "/custom", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 425 // he cannot get "/root" 426 {User: uChuck, Verb: "get", Path: "/root", Resource: "", NS: "", ExpectDecision: authorizer.DecisionNoOpinion}, 427 // but can get any subpath 428 {User: uChuck, Verb: "get", Path: "/root/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 429 {User: uChuck, Verb: "get", Path: "/root/test/1/2/3", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 430 431 // the user "noresource" can get any non-resource request 432 {User: uNoResource, Verb: "get", Path: "", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 433 {User: uNoResource, Verb: "get", Path: "/", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 434 {User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "", NS: "", ExpectDecision: authorizer.DecisionAllow}, 435 // but cannot get any request where IsResourceRequest() == true 436 {User: uNoResource, Verb: "get", Path: "/", Resource: "", NS: "bar", ExpectDecision: authorizer.DecisionNoOpinion}, 437 {User: uNoResource, Verb: "get", Path: "/foo/bar/baz", Resource: "foo", NS: "bar", ExpectDecision: authorizer.DecisionNoOpinion}, 438 439 // Test APIGroup matching 440 {User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectAnyGroup", ExpectDecision: authorizer.DecisionAllow}, 441 {User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectEmptyGroup", ExpectDecision: authorizer.DecisionNoOpinion}, 442 {User: uAPIGroup, Verb: "get", APIGroup: "x", Resource: "foo", NS: "projectXGroup", ExpectDecision: authorizer.DecisionAllow}, 443 } 444 for i, tc := range testCases { 445 attr := authorizer.AttributesRecord{ 446 User: &tc.User, 447 Verb: tc.Verb, 448 Resource: tc.Resource, 449 APIGroup: tc.APIGroup, 450 Namespace: tc.NS, 451 ResourceRequest: len(tc.NS) > 0 || len(tc.Resource) > 0, 452 Path: tc.Path, 453 } 454 // t.Logf("tc %2v: %v -> attr %v", i, tc, attr) 455 decision, _, _ := a.Authorize(context.Background(), attr) 456 if tc.ExpectDecision != decision { 457 t.Errorf("%d: Expected allowed=%v but actually allowed=%v, for case %+v & %+v", 458 i, tc.ExpectDecision, decision, tc, attr) 459 } 460 } 461 } 462 463 func TestSubjectMatches(t *testing.T) { 464 testCases := map[string]struct { 465 User user.DefaultInfo 466 Policy runtime.Object 467 ExpectMatch bool 468 }{ 469 "v0 empty policy does not match unauthed user": { 470 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 471 Policy: &v0.Policy{ 472 User: "", 473 Group: "", 474 }, 475 ExpectMatch: false, 476 }, 477 "v0 * user policy does not match unauthed user": { 478 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 479 Policy: &v0.Policy{ 480 User: "*", 481 Group: "", 482 }, 483 ExpectMatch: false, 484 }, 485 "v0 * group policy does not match unauthed user": { 486 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 487 Policy: &v0.Policy{ 488 User: "", 489 Group: "*", 490 }, 491 ExpectMatch: false, 492 }, 493 "v0 empty policy matches authed user": { 494 User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}}, 495 Policy: &v0.Policy{ 496 User: "", 497 Group: "", 498 }, 499 ExpectMatch: true, 500 }, 501 "v0 empty policy matches authed user with groups": { 502 User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}}, 503 Policy: &v0.Policy{ 504 User: "", 505 Group: "", 506 }, 507 ExpectMatch: true, 508 }, 509 510 "v0 user policy does not match unauthed user": { 511 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 512 Policy: &v0.Policy{ 513 User: "Foo", 514 Group: "", 515 }, 516 ExpectMatch: false, 517 }, 518 "v0 user policy does not match different user": { 519 User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}}, 520 Policy: &v0.Policy{ 521 User: "Foo", 522 Group: "", 523 }, 524 ExpectMatch: false, 525 }, 526 "v0 user policy is case-sensitive": { 527 User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}}, 528 Policy: &v0.Policy{ 529 User: "Foo", 530 Group: "", 531 }, 532 ExpectMatch: false, 533 }, 534 "v0 user policy does not match substring": { 535 User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}}, 536 Policy: &v0.Policy{ 537 User: "Foo", 538 Group: "", 539 }, 540 ExpectMatch: false, 541 }, 542 "v0 user policy matches username": { 543 User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}}, 544 Policy: &v0.Policy{ 545 User: "Foo", 546 Group: "", 547 }, 548 ExpectMatch: true, 549 }, 550 551 "v0 group policy does not match unauthed user": { 552 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 553 Policy: &v0.Policy{ 554 User: "", 555 Group: "Foo", 556 }, 557 ExpectMatch: false, 558 }, 559 "v0 group policy does not match user in different group": { 560 User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}}, 561 Policy: &v0.Policy{ 562 User: "", 563 Group: "A", 564 }, 565 ExpectMatch: false, 566 }, 567 "v0 group policy is case-sensitive": { 568 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 569 Policy: &v0.Policy{ 570 User: "", 571 Group: "b", 572 }, 573 ExpectMatch: false, 574 }, 575 "v0 group policy does not match substring": { 576 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}}, 577 Policy: &v0.Policy{ 578 User: "", 579 Group: "B", 580 }, 581 ExpectMatch: false, 582 }, 583 "v0 group policy matches user in group": { 584 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 585 Policy: &v0.Policy{ 586 User: "", 587 Group: "B", 588 }, 589 ExpectMatch: true, 590 }, 591 592 "v0 user and group policy requires user match": { 593 User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 594 Policy: &v0.Policy{ 595 User: "Foo", 596 Group: "B", 597 }, 598 ExpectMatch: false, 599 }, 600 "v0 user and group policy requires group match": { 601 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 602 Policy: &v0.Policy{ 603 User: "Foo", 604 Group: "D", 605 }, 606 ExpectMatch: false, 607 }, 608 "v0 user and group policy matches": { 609 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 610 Policy: &v0.Policy{ 611 User: "Foo", 612 Group: "B", 613 }, 614 ExpectMatch: true, 615 }, 616 617 "v1 empty policy does not match unauthed user": { 618 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 619 Policy: &v1beta1.Policy{ 620 Spec: v1beta1.PolicySpec{ 621 User: "", 622 Group: "", 623 }, 624 }, 625 ExpectMatch: false, 626 }, 627 "v1 * user policy does not match unauthed user": { 628 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 629 Policy: &v1beta1.Policy{ 630 Spec: v1beta1.PolicySpec{ 631 User: "*", 632 Group: "", 633 }, 634 }, 635 ExpectMatch: false, 636 }, 637 "v1 * group policy does not match unauthed user": { 638 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 639 Policy: &v1beta1.Policy{ 640 Spec: v1beta1.PolicySpec{ 641 User: "", 642 Group: "*", 643 }, 644 }, 645 ExpectMatch: false, 646 }, 647 "v1 empty policy does not match authed user": { 648 User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}}, 649 Policy: &v1beta1.Policy{ 650 Spec: v1beta1.PolicySpec{ 651 User: "", 652 Group: "", 653 }, 654 }, 655 ExpectMatch: false, 656 }, 657 "v1 empty policy does not match authed user with groups": { 658 User: user.DefaultInfo{Name: "Foo", Groups: []string{"a", "b", user.AllAuthenticated}}, 659 Policy: &v1beta1.Policy{ 660 Spec: v1beta1.PolicySpec{ 661 User: "", 662 Group: "", 663 }, 664 }, 665 ExpectMatch: false, 666 }, 667 668 "v1 user policy does not match unauthed user": { 669 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 670 Policy: &v1beta1.Policy{ 671 Spec: v1beta1.PolicySpec{ 672 User: "Foo", 673 Group: "", 674 }, 675 }, 676 ExpectMatch: false, 677 }, 678 "v1 user policy does not match different user": { 679 User: user.DefaultInfo{Name: "Bar", Groups: []string{user.AllAuthenticated}}, 680 Policy: &v1beta1.Policy{ 681 Spec: v1beta1.PolicySpec{ 682 User: "Foo", 683 Group: "", 684 }, 685 }, 686 ExpectMatch: false, 687 }, 688 "v1 user policy is case-sensitive": { 689 User: user.DefaultInfo{Name: "foo", Groups: []string{user.AllAuthenticated}}, 690 Policy: &v1beta1.Policy{ 691 Spec: v1beta1.PolicySpec{ 692 User: "Foo", 693 Group: "", 694 }, 695 }, 696 ExpectMatch: false, 697 }, 698 "v1 user policy does not match substring": { 699 User: user.DefaultInfo{Name: "FooBar", Groups: []string{user.AllAuthenticated}}, 700 Policy: &v1beta1.Policy{ 701 Spec: v1beta1.PolicySpec{ 702 User: "Foo", 703 Group: "", 704 }, 705 }, 706 ExpectMatch: false, 707 }, 708 "v1 user policy matches username": { 709 User: user.DefaultInfo{Name: "Foo", Groups: []string{user.AllAuthenticated}}, 710 Policy: &v1beta1.Policy{ 711 Spec: v1beta1.PolicySpec{ 712 User: "Foo", 713 Group: "", 714 }, 715 }, 716 ExpectMatch: true, 717 }, 718 719 "v1 group policy does not match unauthed user": { 720 User: user.DefaultInfo{Name: "system:anonymous", Groups: []string{"system:unauthenticated"}}, 721 Policy: &v1beta1.Policy{ 722 Spec: v1beta1.PolicySpec{ 723 User: "", 724 Group: "Foo", 725 }, 726 }, 727 ExpectMatch: false, 728 }, 729 "v1 group policy does not match user in different group": { 730 User: user.DefaultInfo{Name: "FooBar", Groups: []string{"B", user.AllAuthenticated}}, 731 Policy: &v1beta1.Policy{ 732 Spec: v1beta1.PolicySpec{ 733 User: "", 734 Group: "A", 735 }, 736 }, 737 ExpectMatch: false, 738 }, 739 "v1 group policy is case-sensitive": { 740 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 741 Policy: &v1beta1.Policy{ 742 Spec: v1beta1.PolicySpec{ 743 User: "", 744 Group: "b", 745 }, 746 }, 747 ExpectMatch: false, 748 }, 749 "v1 group policy does not match substring": { 750 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "BBB", "C", user.AllAuthenticated}}, 751 Policy: &v1beta1.Policy{ 752 Spec: v1beta1.PolicySpec{ 753 User: "", 754 Group: "B", 755 }, 756 }, 757 ExpectMatch: false, 758 }, 759 "v1 group policy matches user in group": { 760 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 761 Policy: &v1beta1.Policy{ 762 Spec: v1beta1.PolicySpec{ 763 User: "", 764 Group: "B", 765 }, 766 }, 767 ExpectMatch: true, 768 }, 769 770 "v1 user and group policy requires user match": { 771 User: user.DefaultInfo{Name: "Bar", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 772 Policy: &v1beta1.Policy{ 773 Spec: v1beta1.PolicySpec{ 774 User: "Foo", 775 Group: "B", 776 }, 777 }, 778 ExpectMatch: false, 779 }, 780 "v1 user and group policy requires group match": { 781 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 782 Policy: &v1beta1.Policy{ 783 Spec: v1beta1.PolicySpec{ 784 User: "Foo", 785 Group: "D", 786 }, 787 }, 788 ExpectMatch: false, 789 }, 790 "v1 user and group policy matches": { 791 User: user.DefaultInfo{Name: "Foo", Groups: []string{"A", "B", "C", user.AllAuthenticated}}, 792 Policy: &v1beta1.Policy{ 793 Spec: v1beta1.PolicySpec{ 794 User: "Foo", 795 Group: "B", 796 }, 797 }, 798 ExpectMatch: true, 799 }, 800 } 801 802 for k, tc := range testCases { 803 policy := &abac.Policy{} 804 if err := abac.Scheme.Convert(tc.Policy, policy, nil); err != nil { 805 t.Errorf("%s: error converting: %v", k, err) 806 continue 807 } 808 attr := authorizer.AttributesRecord{ 809 User: &tc.User, 810 } 811 actualMatch := subjectMatches(*policy, attr.GetUser()) 812 if tc.ExpectMatch != actualMatch { 813 t.Errorf("%v: Expected actorMatches=%v but actually got=%v", 814 k, tc.ExpectMatch, actualMatch) 815 } 816 } 817 } 818 819 func newWithContents(t *testing.T, contents string) (PolicyList, error) { 820 f, err := ioutil.TempFile("", "abac_test") 821 if err != nil { 822 t.Fatalf("unexpected error creating policyfile: %v", err) 823 } 824 f.Close() 825 defer os.Remove(f.Name()) 826 827 if err := ioutil.WriteFile(f.Name(), []byte(contents), 0700); err != nil { 828 t.Fatalf("unexpected error writing policyfile: %v", err) 829 } 830 831 pl, err := NewFromFile(f.Name()) 832 return pl, err 833 } 834 835 func TestPolicy(t *testing.T) { 836 tests := []struct { 837 policy runtime.Object 838 attr authorizer.Attributes 839 matches bool 840 name string 841 }{ 842 // v0 mismatches 843 { 844 policy: &v0.Policy{ 845 Readonly: true, 846 }, 847 attr: authorizer.AttributesRecord{ 848 User: &user.DefaultInfo{ 849 Name: "foo", 850 Groups: []string{user.AllAuthenticated}, 851 }, 852 Verb: "create", 853 }, 854 matches: false, 855 name: "v0 read-only mismatch", 856 }, 857 { 858 policy: &v0.Policy{ 859 User: "foo", 860 }, 861 attr: authorizer.AttributesRecord{ 862 User: &user.DefaultInfo{ 863 Name: "bar", 864 Groups: []string{user.AllAuthenticated}, 865 }, 866 }, 867 matches: false, 868 name: "v0 user name mis-match", 869 }, 870 { 871 policy: &v0.Policy{ 872 Resource: "foo", 873 }, 874 attr: authorizer.AttributesRecord{ 875 User: &user.DefaultInfo{ 876 Name: "foo", 877 Groups: []string{user.AllAuthenticated}, 878 }, 879 Resource: "bar", 880 ResourceRequest: true, 881 }, 882 matches: false, 883 name: "v0 resource mis-match", 884 }, 885 { 886 policy: &v0.Policy{ 887 User: "foo", 888 Resource: "foo", 889 Namespace: "foo", 890 }, 891 attr: authorizer.AttributesRecord{ 892 User: &user.DefaultInfo{ 893 Name: "foo", 894 Groups: []string{user.AllAuthenticated}, 895 }, 896 Resource: "foo", 897 Namespace: "foo", 898 ResourceRequest: true, 899 }, 900 matches: true, 901 name: "v0 namespace mis-match", 902 }, 903 904 // v0 matches 905 { 906 policy: &v0.Policy{}, 907 attr: authorizer.AttributesRecord{ 908 User: &user.DefaultInfo{ 909 Name: "foo", 910 Groups: []string{user.AllAuthenticated}, 911 }, 912 ResourceRequest: true, 913 }, 914 matches: true, 915 name: "v0 null resource", 916 }, 917 { 918 policy: &v0.Policy{ 919 Readonly: true, 920 }, 921 attr: authorizer.AttributesRecord{ 922 User: &user.DefaultInfo{ 923 Name: "foo", 924 Groups: []string{user.AllAuthenticated}, 925 }, 926 Verb: "get", 927 }, 928 matches: true, 929 name: "v0 read-only match", 930 }, 931 { 932 policy: &v0.Policy{ 933 User: "foo", 934 }, 935 attr: authorizer.AttributesRecord{ 936 User: &user.DefaultInfo{ 937 Name: "foo", 938 Groups: []string{user.AllAuthenticated}, 939 }, 940 }, 941 matches: true, 942 name: "v0 user name match", 943 }, 944 { 945 policy: &v0.Policy{ 946 Resource: "foo", 947 }, 948 attr: authorizer.AttributesRecord{ 949 User: &user.DefaultInfo{ 950 Name: "foo", 951 Groups: []string{user.AllAuthenticated}, 952 }, 953 Resource: "foo", 954 ResourceRequest: true, 955 }, 956 matches: true, 957 name: "v0 resource match", 958 }, 959 960 // v1 mismatches 961 { 962 policy: &v1beta1.Policy{}, 963 attr: authorizer.AttributesRecord{ 964 User: &user.DefaultInfo{ 965 Name: "foo", 966 Groups: []string{user.AllAuthenticated}, 967 }, 968 ResourceRequest: true, 969 }, 970 matches: false, 971 name: "v1 null", 972 }, 973 { 974 policy: &v1beta1.Policy{ 975 Spec: v1beta1.PolicySpec{ 976 User: "foo", 977 }, 978 }, 979 attr: authorizer.AttributesRecord{ 980 User: &user.DefaultInfo{ 981 Name: "bar", 982 Groups: []string{user.AllAuthenticated}, 983 }, 984 ResourceRequest: true, 985 }, 986 matches: false, 987 name: "v1 user name mis-match", 988 }, 989 { 990 policy: &v1beta1.Policy{ 991 Spec: v1beta1.PolicySpec{ 992 User: "*", 993 Readonly: true, 994 }, 995 }, 996 attr: authorizer.AttributesRecord{ 997 User: &user.DefaultInfo{ 998 Name: "foo", 999 Groups: []string{user.AllAuthenticated}, 1000 }, 1001 ResourceRequest: true, 1002 }, 1003 matches: false, 1004 name: "v1 read-only mismatch", 1005 }, 1006 { 1007 policy: &v1beta1.Policy{ 1008 Spec: v1beta1.PolicySpec{ 1009 User: "*", 1010 Resource: "foo", 1011 }, 1012 }, 1013 attr: authorizer.AttributesRecord{ 1014 User: &user.DefaultInfo{ 1015 Name: "foo", 1016 Groups: []string{user.AllAuthenticated}, 1017 }, 1018 Resource: "bar", 1019 ResourceRequest: true, 1020 }, 1021 matches: false, 1022 name: "v1 resource mis-match", 1023 }, 1024 { 1025 policy: &v1beta1.Policy{ 1026 Spec: v1beta1.PolicySpec{ 1027 User: "foo", 1028 Namespace: "barr", 1029 Resource: "baz", 1030 }, 1031 }, 1032 attr: authorizer.AttributesRecord{ 1033 User: &user.DefaultInfo{ 1034 Name: "foo", 1035 Groups: []string{user.AllAuthenticated}, 1036 }, 1037 Namespace: "bar", 1038 Resource: "baz", 1039 ResourceRequest: true, 1040 }, 1041 matches: false, 1042 name: "v1 namespace mis-match", 1043 }, 1044 { 1045 policy: &v1beta1.Policy{ 1046 Spec: v1beta1.PolicySpec{ 1047 User: "*", 1048 NonResourcePath: "/api", 1049 }, 1050 }, 1051 attr: authorizer.AttributesRecord{ 1052 User: &user.DefaultInfo{ 1053 Name: "foo", 1054 Groups: []string{user.AllAuthenticated}, 1055 }, 1056 Path: "/api2", 1057 ResourceRequest: false, 1058 }, 1059 matches: false, 1060 name: "v1 non-resource mis-match", 1061 }, 1062 { 1063 policy: &v1beta1.Policy{ 1064 Spec: v1beta1.PolicySpec{ 1065 User: "*", 1066 NonResourcePath: "/api/*", 1067 }, 1068 }, 1069 attr: authorizer.AttributesRecord{ 1070 User: &user.DefaultInfo{ 1071 Name: "foo", 1072 Groups: []string{user.AllAuthenticated}, 1073 }, 1074 Path: "/api2/foo", 1075 ResourceRequest: false, 1076 }, 1077 matches: false, 1078 name: "v1 non-resource wildcard subpath mis-match", 1079 }, 1080 1081 // v1 matches 1082 { 1083 policy: &v1beta1.Policy{ 1084 Spec: v1beta1.PolicySpec{ 1085 User: "foo", 1086 }, 1087 }, 1088 attr: authorizer.AttributesRecord{ 1089 User: &user.DefaultInfo{ 1090 Name: "foo", 1091 Groups: []string{user.AllAuthenticated}, 1092 }, 1093 ResourceRequest: true, 1094 }, 1095 matches: true, 1096 name: "v1 user match", 1097 }, 1098 { 1099 policy: &v1beta1.Policy{ 1100 Spec: v1beta1.PolicySpec{ 1101 User: "*", 1102 }, 1103 }, 1104 attr: authorizer.AttributesRecord{ 1105 User: &user.DefaultInfo{ 1106 Name: "foo", 1107 Groups: []string{user.AllAuthenticated}, 1108 }, 1109 ResourceRequest: true, 1110 }, 1111 matches: true, 1112 name: "v1 user wildcard match", 1113 }, 1114 { 1115 policy: &v1beta1.Policy{ 1116 Spec: v1beta1.PolicySpec{ 1117 Group: "bar", 1118 }, 1119 }, 1120 attr: authorizer.AttributesRecord{ 1121 User: &user.DefaultInfo{ 1122 Name: "foo", 1123 Groups: []string{"bar", user.AllAuthenticated}, 1124 }, 1125 ResourceRequest: true, 1126 }, 1127 matches: true, 1128 name: "v1 group match", 1129 }, 1130 { 1131 policy: &v1beta1.Policy{ 1132 Spec: v1beta1.PolicySpec{ 1133 Group: "*", 1134 }, 1135 }, 1136 attr: authorizer.AttributesRecord{ 1137 User: &user.DefaultInfo{ 1138 Name: "foo", 1139 Groups: []string{"bar", user.AllAuthenticated}, 1140 }, 1141 ResourceRequest: true, 1142 }, 1143 matches: true, 1144 name: "v1 group wildcard match", 1145 }, 1146 { 1147 policy: &v1beta1.Policy{ 1148 Spec: v1beta1.PolicySpec{ 1149 User: "*", 1150 Readonly: true, 1151 }, 1152 }, 1153 attr: authorizer.AttributesRecord{ 1154 User: &user.DefaultInfo{ 1155 Name: "foo", 1156 Groups: []string{user.AllAuthenticated}, 1157 }, 1158 Verb: "get", 1159 ResourceRequest: true, 1160 }, 1161 matches: true, 1162 name: "v1 read-only match", 1163 }, 1164 { 1165 policy: &v1beta1.Policy{ 1166 Spec: v1beta1.PolicySpec{ 1167 User: "*", 1168 Resource: "foo", 1169 }, 1170 }, 1171 attr: authorizer.AttributesRecord{ 1172 User: &user.DefaultInfo{ 1173 Name: "foo", 1174 Groups: []string{user.AllAuthenticated}, 1175 }, 1176 Resource: "foo", 1177 ResourceRequest: true, 1178 }, 1179 matches: true, 1180 name: "v1 resource match", 1181 }, 1182 { 1183 policy: &v1beta1.Policy{ 1184 Spec: v1beta1.PolicySpec{ 1185 User: "foo", 1186 Namespace: "bar", 1187 Resource: "baz", 1188 }, 1189 }, 1190 attr: authorizer.AttributesRecord{ 1191 User: &user.DefaultInfo{ 1192 Name: "foo", 1193 Groups: []string{user.AllAuthenticated}, 1194 }, 1195 Namespace: "bar", 1196 Resource: "baz", 1197 ResourceRequest: true, 1198 }, 1199 matches: true, 1200 name: "v1 namespace match", 1201 }, 1202 { 1203 policy: &v1beta1.Policy{ 1204 Spec: v1beta1.PolicySpec{ 1205 User: "*", 1206 NonResourcePath: "/api", 1207 }, 1208 }, 1209 attr: authorizer.AttributesRecord{ 1210 User: &user.DefaultInfo{ 1211 Name: "foo", 1212 Groups: []string{user.AllAuthenticated}, 1213 }, 1214 Path: "/api", 1215 ResourceRequest: false, 1216 }, 1217 matches: true, 1218 name: "v1 non-resource match", 1219 }, 1220 { 1221 policy: &v1beta1.Policy{ 1222 Spec: v1beta1.PolicySpec{ 1223 User: "*", 1224 NonResourcePath: "*", 1225 }, 1226 }, 1227 attr: authorizer.AttributesRecord{ 1228 User: &user.DefaultInfo{ 1229 Name: "foo", 1230 Groups: []string{user.AllAuthenticated}, 1231 }, 1232 Path: "/api", 1233 ResourceRequest: false, 1234 }, 1235 matches: true, 1236 name: "v1 non-resource wildcard match", 1237 }, 1238 { 1239 policy: &v1beta1.Policy{ 1240 Spec: v1beta1.PolicySpec{ 1241 User: "*", 1242 NonResourcePath: "/api/*", 1243 }, 1244 }, 1245 attr: authorizer.AttributesRecord{ 1246 User: &user.DefaultInfo{ 1247 Name: "foo", 1248 Groups: []string{user.AllAuthenticated}, 1249 }, 1250 Path: "/api/foo", 1251 ResourceRequest: false, 1252 }, 1253 matches: true, 1254 name: "v1 non-resource wildcard subpath match", 1255 }, 1256 } 1257 for _, test := range tests { 1258 policy := &abac.Policy{} 1259 if err := abac.Scheme.Convert(test.policy, policy, nil); err != nil { 1260 t.Errorf("%s: error converting: %v", test.name, err) 1261 continue 1262 } 1263 matches := matches(*policy, test.attr) 1264 if test.matches != matches { 1265 t.Errorf("%s: expected: %t, saw: %t", test.name, test.matches, matches) 1266 continue 1267 } 1268 } 1269 }