k8s.io/kubernetes@v1.29.3/pkg/apis/rbac/validation/validation_test.go (about) 1 /* 2 Copyright 2016 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 validation 18 19 import ( 20 "testing" 21 22 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 23 "k8s.io/apimachinery/pkg/util/validation/field" 24 "k8s.io/kubernetes/pkg/apis/rbac" 25 ) 26 27 func TestValidateClusterRoleBinding(t *testing.T) { 28 errs := ValidateClusterRoleBinding( 29 &rbac.ClusterRoleBinding{ 30 ObjectMeta: metav1.ObjectMeta{Name: "master"}, 31 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 32 Subjects: []rbac.Subject{ 33 {Name: "validsaname", APIGroup: "", Namespace: "foo", Kind: rbac.ServiceAccountKind}, 34 {Name: "valid@username", APIGroup: rbac.GroupName, Kind: rbac.UserKind}, 35 {Name: "valid@groupname", APIGroup: rbac.GroupName, Kind: rbac.GroupKind}, 36 }, 37 }, 38 ) 39 if len(errs) != 0 { 40 t.Errorf("expected success: %v", errs) 41 } 42 43 errorCases := map[string]struct { 44 A rbac.ClusterRoleBinding 45 T field.ErrorType 46 F string 47 }{ 48 "bad group": { 49 A: rbac.ClusterRoleBinding{ 50 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 51 RoleRef: rbac.RoleRef{APIGroup: "rbac.GroupName", Kind: "ClusterRole", Name: "valid"}, 52 }, 53 T: field.ErrorTypeNotSupported, 54 F: "roleRef.apiGroup", 55 }, 56 "bad kind": { 57 A: rbac.ClusterRoleBinding{ 58 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 59 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Type", Name: "valid"}, 60 }, 61 T: field.ErrorTypeNotSupported, 62 F: "roleRef.kind", 63 }, 64 "reference role": { 65 A: rbac.ClusterRoleBinding{ 66 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 67 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 68 }, 69 T: field.ErrorTypeNotSupported, 70 F: "roleRef.kind", 71 }, 72 "zero-length name": { 73 A: rbac.ClusterRoleBinding{ 74 ObjectMeta: metav1.ObjectMeta{}, 75 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 76 }, 77 T: field.ErrorTypeRequired, 78 F: "metadata.name", 79 }, 80 "bad role": { 81 A: rbac.ClusterRoleBinding{ 82 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 83 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole"}, 84 }, 85 T: field.ErrorTypeRequired, 86 F: "roleRef.name", 87 }, 88 "bad subject kind": { 89 A: rbac.ClusterRoleBinding{ 90 ObjectMeta: metav1.ObjectMeta{Name: "master"}, 91 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 92 Subjects: []rbac.Subject{{Name: "subject"}}, 93 }, 94 T: field.ErrorTypeNotSupported, 95 F: "subjects[0].kind", 96 }, 97 "bad subject name": { 98 A: rbac.ClusterRoleBinding{ 99 ObjectMeta: metav1.ObjectMeta{Name: "master"}, 100 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 101 Subjects: []rbac.Subject{{Namespace: "foo", Name: "subject:bad", Kind: rbac.ServiceAccountKind}}, 102 }, 103 T: field.ErrorTypeInvalid, 104 F: "subjects[0].name", 105 }, 106 "missing SA namespace": { 107 A: rbac.ClusterRoleBinding{ 108 ObjectMeta: metav1.ObjectMeta{Name: "master"}, 109 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 110 Subjects: []rbac.Subject{{Name: "good", Kind: rbac.ServiceAccountKind}}, 111 }, 112 T: field.ErrorTypeRequired, 113 F: "subjects[0].namespace", 114 }, 115 "missing subject name": { 116 A: rbac.ClusterRoleBinding{ 117 ObjectMeta: metav1.ObjectMeta{Name: "master"}, 118 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "ClusterRole", Name: "valid"}, 119 Subjects: []rbac.Subject{{Namespace: "foo", Kind: rbac.ServiceAccountKind}}, 120 }, 121 T: field.ErrorTypeRequired, 122 F: "subjects[0].name", 123 }, 124 } 125 for k, v := range errorCases { 126 errs := ValidateClusterRoleBinding(&v.A) 127 if len(errs) == 0 { 128 t.Errorf("expected failure %s for %v", k, v.A) 129 continue 130 } 131 for i := range errs { 132 if errs[i].Type != v.T { 133 t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) 134 } 135 if errs[i].Field != v.F { 136 t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) 137 } 138 } 139 } 140 } 141 142 func TestValidateRoleBinding(t *testing.T) { 143 errs := ValidateRoleBinding( 144 &rbac.RoleBinding{ 145 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master"}, 146 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 147 Subjects: []rbac.Subject{ 148 {Name: "validsaname", APIGroup: "", Kind: rbac.ServiceAccountKind}, 149 {Name: "valid@username", APIGroup: rbac.GroupName, Kind: rbac.UserKind}, 150 {Name: "valid@groupname", APIGroup: rbac.GroupName, Kind: rbac.GroupKind}, 151 }, 152 }, 153 ) 154 if len(errs) != 0 { 155 t.Errorf("expected success: %v", errs) 156 } 157 158 errorCases := map[string]struct { 159 A rbac.RoleBinding 160 T field.ErrorType 161 F string 162 }{ 163 "bad group": { 164 A: rbac.RoleBinding{ 165 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "default"}, 166 RoleRef: rbac.RoleRef{APIGroup: "rbac.GroupName", Kind: "ClusterRole", Name: "valid"}, 167 }, 168 T: field.ErrorTypeNotSupported, 169 F: "roleRef.apiGroup", 170 }, 171 "bad kind": { 172 A: rbac.RoleBinding{ 173 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "default"}, 174 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Type", Name: "valid"}, 175 }, 176 T: field.ErrorTypeNotSupported, 177 F: "roleRef.kind", 178 }, 179 "zero-length namespace": { 180 A: rbac.RoleBinding{ 181 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 182 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 183 }, 184 T: field.ErrorTypeRequired, 185 F: "metadata.namespace", 186 }, 187 "zero-length name": { 188 A: rbac.RoleBinding{ 189 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault}, 190 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 191 }, 192 T: field.ErrorTypeRequired, 193 F: "metadata.name", 194 }, 195 "bad role": { 196 A: rbac.RoleBinding{ 197 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "default"}, 198 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role"}, 199 }, 200 T: field.ErrorTypeRequired, 201 F: "roleRef.name", 202 }, 203 "bad subject kind": { 204 A: rbac.RoleBinding{ 205 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master"}, 206 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 207 Subjects: []rbac.Subject{{Name: "subject"}}, 208 }, 209 T: field.ErrorTypeNotSupported, 210 F: "subjects[0].kind", 211 }, 212 "bad subject name": { 213 A: rbac.RoleBinding{ 214 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master"}, 215 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 216 Subjects: []rbac.Subject{{Name: "subject:bad", Kind: rbac.ServiceAccountKind}}, 217 }, 218 T: field.ErrorTypeInvalid, 219 F: "subjects[0].name", 220 }, 221 "missing subject name": { 222 A: rbac.RoleBinding{ 223 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master"}, 224 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 225 Subjects: []rbac.Subject{{Kind: rbac.ServiceAccountKind}}, 226 }, 227 T: field.ErrorTypeRequired, 228 F: "subjects[0].name", 229 }, 230 } 231 for k, v := range errorCases { 232 errs := ValidateRoleBinding(&v.A) 233 if len(errs) == 0 { 234 t.Errorf("expected failure %s for %v", k, v.A) 235 continue 236 } 237 for i := range errs { 238 if errs[i].Type != v.T { 239 t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) 240 } 241 if errs[i].Field != v.F { 242 t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) 243 } 244 } 245 } 246 } 247 248 func TestValidateRoleBindingUpdate(t *testing.T) { 249 old := &rbac.RoleBinding{ 250 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master", ResourceVersion: "1"}, 251 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 252 } 253 254 errs := ValidateRoleBindingUpdate( 255 &rbac.RoleBinding{ 256 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master", ResourceVersion: "1"}, 257 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "valid"}, 258 }, 259 old, 260 ) 261 if len(errs) != 0 { 262 t.Errorf("expected success: %v", errs) 263 } 264 265 errorCases := map[string]struct { 266 A rbac.RoleBinding 267 T field.ErrorType 268 F string 269 }{ 270 "changedRef": { 271 A: rbac.RoleBinding{ 272 ObjectMeta: metav1.ObjectMeta{Namespace: metav1.NamespaceDefault, Name: "master", ResourceVersion: "1"}, 273 RoleRef: rbac.RoleRef{APIGroup: rbac.GroupName, Kind: "Role", Name: "changed"}, 274 }, 275 T: field.ErrorTypeInvalid, 276 F: "roleRef", 277 }, 278 } 279 for k, v := range errorCases { 280 errs := ValidateRoleBindingUpdate(&v.A, old) 281 if len(errs) == 0 { 282 t.Errorf("expected failure %s for %v", k, v.A) 283 continue 284 } 285 for i := range errs { 286 if errs[i].Type != v.T { 287 t.Errorf("%s: expected errors to have type %s: %v", k, v.T, errs[i]) 288 } 289 if errs[i].Field != v.F { 290 t.Errorf("%s: expected errors to have field %s: %v", k, v.F, errs[i]) 291 } 292 } 293 } 294 } 295 296 type ValidateRoleTest struct { 297 role rbac.Role 298 wantErr bool 299 errType field.ErrorType 300 field string 301 } 302 303 func (v ValidateRoleTest) test(t *testing.T) { 304 errs := ValidateRole(&v.role) 305 if len(errs) == 0 { 306 if v.wantErr { 307 t.Fatal("expected validation error") 308 } 309 return 310 } 311 if !v.wantErr { 312 t.Errorf("didn't expect error, got %v", errs) 313 return 314 } 315 for i := range errs { 316 if errs[i].Type != v.errType { 317 t.Errorf("expected errors to have type %s: %v", v.errType, errs[i]) 318 } 319 if errs[i].Field != v.field { 320 t.Errorf("expected errors to have field %s: %v", v.field, errs[i]) 321 } 322 } 323 } 324 325 type ValidateClusterRoleTest struct { 326 role rbac.ClusterRole 327 wantErr bool 328 errType field.ErrorType 329 field string 330 } 331 332 func (v ValidateClusterRoleTest) test(t *testing.T) { 333 errs := ValidateClusterRole(&v.role, ClusterRoleValidationOptions{false}) 334 if len(errs) == 0 { 335 if v.wantErr { 336 t.Fatal("expected validation error") 337 } 338 return 339 } 340 if !v.wantErr { 341 t.Errorf("didn't expect error, got %v", errs) 342 return 343 } 344 for i := range errs { 345 if errs[i].Type != v.errType { 346 t.Errorf("expected errors to have type %s: %v", v.errType, errs[i]) 347 } 348 if errs[i].Field != v.field { 349 t.Errorf("expected errors to have field %s: %v", v.field, errs[i]) 350 } 351 } 352 } 353 354 func TestValidateRoleZeroLengthNamespace(t *testing.T) { 355 ValidateRoleTest{ 356 role: rbac.Role{ 357 ObjectMeta: metav1.ObjectMeta{Name: "default"}, 358 }, 359 wantErr: true, 360 errType: field.ErrorTypeRequired, 361 field: "metadata.namespace", 362 }.test(t) 363 } 364 365 func TestValidateRoleZeroLengthName(t *testing.T) { 366 ValidateRoleTest{ 367 role: rbac.Role{ 368 ObjectMeta: metav1.ObjectMeta{Namespace: "default"}, 369 }, 370 wantErr: true, 371 errType: field.ErrorTypeRequired, 372 field: "metadata.name", 373 }.test(t) 374 } 375 376 func TestValidateRoleValidRole(t *testing.T) { 377 ValidateRoleTest{ 378 role: rbac.Role{ 379 ObjectMeta: metav1.ObjectMeta{ 380 Namespace: "default", 381 Name: "default", 382 }, 383 }, 384 wantErr: false, 385 }.test(t) 386 } 387 388 func TestValidateRoleValidRoleNoNamespace(t *testing.T) { 389 ValidateClusterRoleTest{ 390 role: rbac.ClusterRole{ 391 ObjectMeta: metav1.ObjectMeta{ 392 Name: "default", 393 }, 394 }, 395 wantErr: false, 396 }.test(t) 397 } 398 399 func TestValidateRoleNonResourceURL(t *testing.T) { 400 ValidateClusterRoleTest{ 401 role: rbac.ClusterRole{ 402 ObjectMeta: metav1.ObjectMeta{ 403 Name: "default", 404 }, 405 Rules: []rbac.PolicyRule{{ 406 Verbs: []string{"get"}, 407 NonResourceURLs: []string{"/*"}, 408 }}, 409 }, 410 wantErr: false, 411 }.test(t) 412 } 413 414 func TestValidateRoleNamespacedNonResourceURL(t *testing.T) { 415 ValidateRoleTest{ 416 role: rbac.Role{ 417 ObjectMeta: metav1.ObjectMeta{ 418 Namespace: "default", 419 Name: "default", 420 }, 421 Rules: []rbac.PolicyRule{{ 422 // non-resource URLs are invalid for namespaced rules 423 Verbs: []string{"get"}, 424 NonResourceURLs: []string{"/*"}, 425 }}, 426 }, 427 wantErr: true, 428 errType: field.ErrorTypeInvalid, 429 field: "rules[0].nonResourceURLs", 430 }.test(t) 431 } 432 433 func TestValidateRoleNonResourceURLNoVerbs(t *testing.T) { 434 ValidateClusterRoleTest{ 435 role: rbac.ClusterRole{ 436 ObjectMeta: metav1.ObjectMeta{ 437 Name: "default", 438 }, 439 Rules: []rbac.PolicyRule{{ 440 Verbs: []string{}, 441 NonResourceURLs: []string{"/*"}, 442 }}, 443 }, 444 wantErr: true, 445 errType: field.ErrorTypeRequired, 446 field: "rules[0].verbs", 447 }.test(t) 448 } 449 450 func TestValidateRoleMixedNonResourceAndResource(t *testing.T) { 451 ValidateRoleTest{ 452 role: rbac.Role{ 453 ObjectMeta: metav1.ObjectMeta{ 454 Name: "default", 455 Namespace: "default", 456 }, 457 Rules: []rbac.PolicyRule{{ 458 Verbs: []string{"get"}, 459 NonResourceURLs: []string{"/*"}, 460 APIGroups: []string{"v1"}, 461 Resources: []string{"pods"}, 462 }}, 463 }, 464 wantErr: true, 465 errType: field.ErrorTypeInvalid, 466 field: "rules[0].nonResourceURLs", 467 }.test(t) 468 } 469 470 func TestValidateRoleValidResource(t *testing.T) { 471 ValidateRoleTest{ 472 role: rbac.Role{ 473 ObjectMeta: metav1.ObjectMeta{ 474 Name: "default", 475 Namespace: "default", 476 }, 477 Rules: []rbac.PolicyRule{{ 478 Verbs: []string{"get"}, 479 APIGroups: []string{"v1"}, 480 Resources: []string{"pods"}, 481 }}, 482 }, 483 wantErr: false, 484 }.test(t) 485 } 486 487 func TestValidateRoleNoAPIGroup(t *testing.T) { 488 ValidateRoleTest{ 489 role: rbac.Role{ 490 ObjectMeta: metav1.ObjectMeta{ 491 Name: "default", 492 Namespace: "default", 493 }, 494 Rules: []rbac.PolicyRule{{ 495 Verbs: []string{"get"}, 496 Resources: []string{"pods"}, 497 }}, 498 }, 499 wantErr: true, 500 errType: field.ErrorTypeRequired, 501 field: "rules[0].apiGroups", 502 }.test(t) 503 } 504 505 func TestValidateRoleNoResources(t *testing.T) { 506 ValidateRoleTest{ 507 role: rbac.Role{ 508 ObjectMeta: metav1.ObjectMeta{ 509 Name: "default", 510 Namespace: "default", 511 }, 512 Rules: []rbac.PolicyRule{{ 513 Verbs: []string{"get"}, 514 APIGroups: []string{"v1"}, 515 }}, 516 }, 517 wantErr: true, 518 errType: field.ErrorTypeRequired, 519 field: "rules[0].resources", 520 }.test(t) 521 }