github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/atc/api/accessor/accessor_test.go (about) 1 package accessor_test 2 3 import ( 4 . "github.com/onsi/ginkgo" 5 . "github.com/onsi/ginkgo/extensions/table" 6 . "github.com/onsi/gomega" 7 8 "github.com/pf-qiu/concourse/v6/atc" 9 "github.com/pf-qiu/concourse/v6/atc/api/accessor" 10 "github.com/pf-qiu/concourse/v6/atc/db" 11 "github.com/pf-qiu/concourse/v6/atc/db/dbfakes" 12 ) 13 14 var _ = Describe("Accessor", func() { 15 var ( 16 verification accessor.Verification 17 requiredRole string 18 teams []db.Team 19 access accessor.Access 20 21 fakeTeam1 *dbfakes.FakeTeam 22 fakeTeam2 *dbfakes.FakeTeam 23 fakeTeam3 *dbfakes.FakeTeam 24 ) 25 26 BeforeEach(func() { 27 fakeTeam1 = new(dbfakes.FakeTeam) 28 fakeTeam1.NameReturns("some-team-1") 29 fakeTeam2 = new(dbfakes.FakeTeam) 30 fakeTeam2.NameReturns("some-team-2") 31 fakeTeam3 = new(dbfakes.FakeTeam) 32 fakeTeam3.NameReturns("some-team-3") 33 34 verification = accessor.Verification{} 35 36 teams = []db.Team{fakeTeam1, fakeTeam2, fakeTeam3} 37 }) 38 39 JustBeforeEach(func() { 40 access = accessor.NewAccessor(verification, requiredRole, "sub", []string{"system"}, teams) 41 }) 42 43 Describe("HasToken", func() { 44 var result bool 45 46 JustBeforeEach(func() { 47 result = access.HasToken() 48 }) 49 50 Context("when verification does not have a token", func() { 51 BeforeEach(func() { 52 verification.HasToken = false 53 }) 54 55 It("returns false", func() { 56 Expect(result).To(BeFalse()) 57 }) 58 }) 59 60 Context("when verification has a token", func() { 61 BeforeEach(func() { 62 verification.HasToken = true 63 }) 64 65 It("returns true", func() { 66 Expect(result).To(BeTrue()) 67 }) 68 }) 69 }) 70 71 Describe("IsAuthenticated", func() { 72 var result bool 73 74 JustBeforeEach(func() { 75 result = access.IsAuthenticated() 76 }) 77 78 Context("when verification does not have a token", func() { 79 BeforeEach(func() { 80 verification.HasToken = false 81 }) 82 83 It("returns false", func() { 84 Expect(result).To(BeFalse()) 85 }) 86 }) 87 88 Context("when verification has a token", func() { 89 BeforeEach(func() { 90 verification.HasToken = true 91 }) 92 93 Context("when verification token is not valid", func() { 94 BeforeEach(func() { 95 verification.IsTokenValid = false 96 }) 97 98 It("returns false", func() { 99 Expect(result).To(BeFalse()) 100 }) 101 }) 102 103 Context("when verification token is valid", func() { 104 BeforeEach(func() { 105 verification.IsTokenValid = true 106 }) 107 108 It("returns true", func() { 109 Expect(result).To(BeTrue()) 110 }) 111 }) 112 }) 113 }) 114 115 Describe("IsAuthorized", func() { 116 var result bool 117 118 JustBeforeEach(func() { 119 result = access.IsAuthorized("some-team") 120 }) 121 122 Context("when the user has no token", func() { 123 BeforeEach(func() { 124 verification.HasToken = false 125 }) 126 127 It("returns false", func() { 128 Expect(result).To(BeFalse()) 129 }) 130 }) 131 132 Context("when the user has invalid token", func() { 133 BeforeEach(func() { 134 verification.HasToken = true 135 verification.IsTokenValid = false 136 }) 137 138 It("returns false", func() { 139 Expect(result).To(BeFalse()) 140 }) 141 }) 142 143 Context("when the user has valid token", func() { 144 BeforeEach(func() { 145 verification.HasToken = true 146 verification.IsTokenValid = true 147 verification.RawClaims = map[string]interface{}{ 148 "federated_claims": map[string]interface{}{ 149 "connector_id": "some-connector", 150 "user_id": "some-user-id", 151 }, 152 } 153 }) 154 155 Context("when the user is part of any admin team", func() { 156 BeforeEach(func() { 157 fakeTeam1.NameReturns("not-some-team") 158 fakeTeam1.AdminReturns(true) 159 fakeTeam1.AuthReturns(atc.TeamAuth{ 160 "owner": map[string][]string{ 161 "users": {"some-connector:some-user-id"}, 162 }, 163 }) 164 }) 165 166 It("returns true", func() { 167 Expect(result).To(BeTrue()) 168 }) 169 }) 170 }) 171 }) 172 173 DescribeTable("IsAuthorized for users", 174 func(requiredRole string, actualRole string, expected bool) { 175 176 verification.HasToken = true 177 verification.IsTokenValid = true 178 verification.RawClaims = map[string]interface{}{ 179 "federated_claims": map[string]interface{}{ 180 "connector_id": "some-connector", 181 "user_id": "some-user-id", 182 }, 183 } 184 185 fakeTeam1.NameReturns("some-team") 186 fakeTeam1.AdminReturns(true) 187 fakeTeam1.AuthReturns(atc.TeamAuth{ 188 actualRole: map[string][]string{ 189 "users": {"some-connector:some-user-id"}, 190 }, 191 }) 192 193 access = accessor.NewAccessor(verification, requiredRole, "sub", []string{"system"}, teams) 194 result := access.IsAuthorized("some-team") 195 Expect(expected).Should(Equal(result)) 196 }, 197 198 Entry("viewer attempting viewer action", "viewer", "viewer", true), 199 Entry("pipeline-operator attempting viewer action", "viewer", "pipeline-operator", true), 200 Entry("member attempting viewer action", "viewer", "member", true), 201 Entry("owner attempting viewer action", "viewer", "owner", true), 202 203 Entry("viewer attempting pipeline-operator action", "pipeline-operator", "viewer", false), 204 Entry("pipeline-operator attempting pipeline-operator action", "pipeline-operator", "pipeline-operator", true), 205 Entry("member attempting pipeline-operator action", "pipeline-operator", "member", true), 206 Entry("owner attempting pipeline-operator action", "pipeline-operator", "owner", true), 207 208 Entry("viewer attempting member action", "member", "viewer", false), 209 Entry("pipeline-operator attempting member action", "member", "pipeline-operator", false), 210 Entry("member attempting member action", "member", "member", true), 211 Entry("owner attempting member action", "member", "owner", true), 212 213 Entry("viewer attempting owner action", "owner", "viewer", false), 214 Entry("pipeline-operator attempting owner action", "owner", "pipeline-operator", false), 215 Entry("member attempting owner action", "owner", "member", false), 216 Entry("owner attempting owner action", "owner", "owner", true), 217 ) 218 219 DescribeTable("IsAuthorized for groups", 220 func(requiredRole string, actualRole string, expected bool) { 221 222 verification.HasToken = true 223 verification.IsTokenValid = true 224 225 verification.RawClaims = map[string]interface{}{ 226 "groups": []interface{}{"some-group"}, 227 "federated_claims": map[string]interface{}{ 228 "connector_id": "some-connector", 229 }, 230 } 231 232 fakeTeam1.NameReturns("some-team") 233 fakeTeam1.AdminReturns(true) 234 fakeTeam1.AuthReturns(atc.TeamAuth{ 235 actualRole: map[string][]string{ 236 "groups": {"some-connector:some-group"}, 237 }, 238 }) 239 240 access = accessor.NewAccessor(verification, requiredRole, "sub", []string{"system"}, teams) 241 result := access.IsAuthorized("some-team") 242 Expect(expected).Should(Equal(result)) 243 }, 244 245 Entry("viewer attempting viewer action", "viewer", "viewer", true), 246 Entry("pipeline-operator attempting viewer action", "viewer", "pipeline-operator", true), 247 Entry("member attempting viewer action", "viewer", "member", true), 248 Entry("owner attempting viewer action", "viewer", "owner", true), 249 250 Entry("viewer attempting pipeline-operator action", "pipeline-operator", "viewer", false), 251 Entry("pipeline-operator attempting pipeline-operator action", "pipeline-operator", "pipeline-operator", true), 252 Entry("member attempting pipeline-operator action", "pipeline-operator", "member", true), 253 Entry("owner attempting pipeline-operator action", "pipeline-operator", "owner", true), 254 255 Entry("viewer attempting member action", "member", "viewer", false), 256 Entry("pipeline-operator attempting member action", "member", "pipeline-operator", false), 257 Entry("member attempting member action", "member", "member", true), 258 Entry("owner attempting member action", "member", "owner", true), 259 260 Entry("viewer attempting owner action", "owner", "viewer", false), 261 Entry("pipeline-operator attempting owner action", "owner", "pipeline-operator", false), 262 Entry("member attempting owner action", "owner", "member", false), 263 Entry("owner attempting owner action", "owner", "owner", true), 264 ) 265 266 Describe("TeamNames", func() { 267 var result []string 268 269 JustBeforeEach(func() { 270 result = access.TeamNames() 271 }) 272 273 Context("when the user has no token", func() { 274 BeforeEach(func() { 275 verification.HasToken = false 276 }) 277 278 It("returns nothing", func() { 279 Expect(result).To(BeEmpty()) 280 }) 281 }) 282 283 Context("when the user has invalid token", func() { 284 BeforeEach(func() { 285 verification.HasToken = true 286 verification.IsTokenValid = false 287 }) 288 289 It("returns nothing", func() { 290 Expect(result).To(BeEmpty()) 291 }) 292 }) 293 294 Context("when the user has valid token", func() { 295 BeforeEach(func() { 296 verification.HasToken = true 297 verification.IsTokenValid = true 298 verification.RawClaims = map[string]interface{}{ 299 "federated_claims": map[string]interface{}{ 300 "connector_id": "some-connector", 301 "user_id": "some-user-id", 302 }, 303 } 304 }) 305 306 Context("when the user is part of any admin team", func() { 307 BeforeEach(func() { 308 fakeTeam1.AdminReturns(true) 309 fakeTeam1.AuthReturns(atc.TeamAuth{ 310 "owner": map[string][]string{ 311 "users": {"some-connector:some-user-id"}, 312 }, 313 }) 314 }) 315 316 It("returns all teams", func() { 317 Expect(result).To(ConsistOf( 318 "some-team-1", 319 "some-team-2", 320 "some-team-3", 321 )) 322 }) 323 }) 324 325 Context("the team has the user configured", func() { 326 327 BeforeEach(func() { 328 fakeTeam1.AuthReturns(atc.TeamAuth{ 329 "owner": map[string][]string{ 330 "users": {"some-connector:some-user-id"}, 331 }, 332 }) 333 fakeTeam2.AuthReturns(atc.TeamAuth{ 334 "member": map[string][]string{ 335 "users": {"some-connector:some-user-id"}, 336 }, 337 }) 338 fakeTeam3.AuthReturns(atc.TeamAuth{ 339 "viewer": map[string][]string{ 340 "users": {"some-connector:some-user-id"}, 341 }, 342 }) 343 }) 344 345 Context("when the action requires a 'viewer' role", func() { 346 BeforeEach(func() { 347 requiredRole = "viewer" 348 }) 349 350 It("returns all teams", func() { 351 Expect(result).To(ConsistOf( 352 "some-team-1", 353 "some-team-2", 354 "some-team-3", 355 )) 356 }) 357 }) 358 359 Context("when the action requires a 'member' role", func() { 360 BeforeEach(func() { 361 requiredRole = "member" 362 }) 363 364 It("returns all teams", func() { 365 Expect(result).To(ConsistOf( 366 "some-team-1", 367 "some-team-2", 368 )) 369 }) 370 }) 371 372 Context("when the action requires an 'owner' role", func() { 373 BeforeEach(func() { 374 requiredRole = "owner" 375 }) 376 377 It("returns all teams", func() { 378 Expect(result).To(ConsistOf( 379 "some-team-1", 380 )) 381 }) 382 }) 383 }) 384 }) 385 }) 386 387 Describe("IsAdmin", func() { 388 var result bool 389 390 JustBeforeEach(func() { 391 result = access.IsAdmin() 392 }) 393 394 Context("when the user has no token", func() { 395 BeforeEach(func() { 396 verification.HasToken = false 397 }) 398 399 It("returns false", func() { 400 Expect(result).To(BeFalse()) 401 }) 402 }) 403 404 Context("when the user has invalid token", func() { 405 BeforeEach(func() { 406 verification.HasToken = true 407 verification.IsTokenValid = false 408 }) 409 410 It("returns false", func() { 411 Expect(result).To(BeFalse()) 412 }) 413 }) 414 415 Context("when the user has valid token", func() { 416 BeforeEach(func() { 417 verification.HasToken = true 418 verification.IsTokenValid = true 419 verification.RawClaims = map[string]interface{}{ 420 "federated_claims": map[string]interface{}{ 421 "connector_id": "some-connector", 422 "user_id": "some-user-id", 423 }, 424 } 425 }) 426 427 Context("when the user is a not on an admin team", func() { 428 BeforeEach(func() { 429 fakeTeam1.AuthReturns(atc.TeamAuth{ 430 "viewer": map[string][]string{ 431 "users": {"some-connector:some-user-id"}, 432 }, 433 }) 434 fakeTeam2.AuthReturns(atc.TeamAuth{ 435 "member": map[string][]string{ 436 "users": {"some-connector:some-user-id"}, 437 }, 438 }) 439 fakeTeam3.AuthReturns(atc.TeamAuth{ 440 "owner": map[string][]string{ 441 "users": {"some-connector:some-user-id"}, 442 }, 443 }) 444 }) 445 446 It("returns false", func() { 447 Expect(result).To(BeFalse()) 448 }) 449 }) 450 451 Context("when the user is a 'viewer' on an admin team", func() { 452 BeforeEach(func() { 453 fakeTeam1.AdminReturns(true) 454 fakeTeam1.AuthReturns(atc.TeamAuth{ 455 "viewer": map[string][]string{ 456 "users": {"some-connector:some-user-id"}, 457 }, 458 }) 459 }) 460 461 It("returns false", func() { 462 Expect(result).To(BeFalse()) 463 }) 464 }) 465 466 Context("when the user is a 'member' on an admin team", func() { 467 BeforeEach(func() { 468 fakeTeam1.AdminReturns(true) 469 fakeTeam1.AuthReturns(atc.TeamAuth{ 470 "member": map[string][]string{ 471 "users": {"some-connector:some-user-id"}, 472 }, 473 }) 474 }) 475 476 It("returns false", func() { 477 Expect(result).To(BeFalse()) 478 }) 479 }) 480 481 Context("when the user is a 'owner' on an admin team", func() { 482 BeforeEach(func() { 483 fakeTeam1.AdminReturns(true) 484 fakeTeam1.AuthReturns(atc.TeamAuth{ 485 "owner": map[string][]string{ 486 "users": []string{"some-connector:some-user-id"}, 487 }, 488 }) 489 }) 490 491 It("returns true", func() { 492 Expect(result).To(BeTrue()) 493 }) 494 }) 495 }) 496 }) 497 498 Describe("IsSystem", func() { 499 var result bool 500 501 JustBeforeEach(func() { 502 result = access.IsSystem() 503 }) 504 505 Context("when the user has no token", func() { 506 BeforeEach(func() { 507 verification.HasToken = false 508 }) 509 510 It("returns false", func() { 511 Expect(result).To(BeFalse()) 512 }) 513 }) 514 515 Context("when the user has invalid token", func() { 516 BeforeEach(func() { 517 verification.HasToken = true 518 verification.IsTokenValid = false 519 }) 520 521 It("returns false", func() { 522 Expect(result).To(BeFalse()) 523 }) 524 }) 525 526 Context("when the token does not have the system sub", func() { 527 BeforeEach(func() { 528 verification.HasToken = true 529 verification.IsTokenValid = true 530 verification.RawClaims = map[string]interface{}{ 531 "sub": "not-system", 532 } 533 }) 534 535 It("returns false", func() { 536 Expect(result).To(BeFalse()) 537 }) 538 }) 539 540 Context("when the token does have the system sub", func() { 541 BeforeEach(func() { 542 verification.HasToken = true 543 verification.IsTokenValid = true 544 verification.RawClaims = map[string]interface{}{ 545 "sub": "system", 546 } 547 }) 548 549 It("returns true", func() { 550 Expect(result).To(BeTrue()) 551 }) 552 }) 553 }) 554 555 Describe("Claims", func() { 556 var result accessor.Claims 557 558 JustBeforeEach(func() { 559 result = access.Claims() 560 }) 561 562 Context("when the user has no token", func() { 563 BeforeEach(func() { 564 verification.HasToken = false 565 }) 566 567 It("returns empty", func() { 568 Expect(result).To(Equal(accessor.Claims{})) 569 }) 570 }) 571 572 Context("when the user has invalid token", func() { 573 BeforeEach(func() { 574 verification.HasToken = true 575 verification.IsTokenValid = false 576 }) 577 578 It("returns empty", func() { 579 Expect(result).To(Equal(accessor.Claims{})) 580 }) 581 }) 582 583 Context("when the token has a preferred user_name", func() { 584 BeforeEach(func() { 585 verification.HasToken = true 586 verification.IsTokenValid = true 587 verification.RawClaims = map[string]interface{}{ 588 "sub": "some-sub", 589 "name": "some-name", 590 "preferred_username": "some-user-name", 591 "email": "some-email", 592 "federated_claims": map[string]interface{}{ 593 "user_id": "some-id", 594 "connector_id": "some-connector", 595 }, 596 } 597 }) 598 599 It("returns the result", func() { 600 Expect(result).To(Equal(accessor.Claims{ 601 Sub: "some-sub", 602 UserName: "some-name", 603 Email: "some-email", 604 UserID: "some-id", 605 PreferredUsername: "some-user-name", 606 Connector: "some-connector", 607 })) 608 }) 609 }) 610 }) 611 612 Describe("TeamRoles", func() { 613 var result map[string][]string 614 615 JustBeforeEach(func() { 616 result = access.TeamRoles() 617 }) 618 619 Context("when the user has no token", func() { 620 BeforeEach(func() { 621 verification.HasToken = false 622 }) 623 624 It("returns empty", func() { 625 Expect(result).To(Equal(map[string][]string{})) 626 }) 627 }) 628 629 Context("when the user has invalid token", func() { 630 BeforeEach(func() { 631 verification.HasToken = true 632 verification.IsTokenValid = false 633 }) 634 635 It("returns empty", func() { 636 Expect(result).To(Equal(map[string][]string{})) 637 }) 638 }) 639 640 Context("when the token has claims", func() { 641 BeforeEach(func() { 642 verification.HasToken = true 643 verification.IsTokenValid = true 644 verification.RawClaims = map[string]interface{}{ 645 "sub": "some-sub", 646 "name": "some-name", 647 "preferred_username": "some-user-name", 648 "email": "some-email", 649 "federated_claims": map[string]interface{}{ 650 "connector_id": "some-connector", 651 "user_id": "some-user-id", 652 }, 653 "groups": []interface{}{"some-group"}, 654 } 655 }) 656 657 Context("when the user is not part of any teams", func() { 658 It("returns empty", func() { 659 Expect(result).To(Equal(map[string][]string{})) 660 }) 661 }) 662 663 Context("when the user is granted a role from their user id", func() { 664 BeforeEach(func() { 665 fakeTeam1.AuthReturns(atc.TeamAuth{ 666 "owner": map[string][]string{ 667 "users": {"some-connector:some-user-id"}, 668 }, 669 }) 670 fakeTeam2.AuthReturns(atc.TeamAuth{ 671 "member": map[string][]string{ 672 "users": {"some-connector:some-user-id"}, 673 }, 674 }) 675 fakeTeam3.AuthReturns(atc.TeamAuth{ 676 "viewer": map[string][]string{ 677 "users": {"some-connector:some-user-id"}, 678 }, 679 }) 680 }) 681 682 It("returns result with teams", func() { 683 Expect(result["some-team-1"]).To(ContainElement("owner")) 684 Expect(result["some-team-2"]).To(ContainElement("member")) 685 Expect(result["some-team-3"]).To(ContainElement("viewer")) 686 }) 687 }) 688 689 Context("when the user is granted a role from their user name", func() { 690 BeforeEach(func() { 691 fakeTeam1.AuthReturns(atc.TeamAuth{ 692 "owner": map[string][]string{ 693 "users": {"some-connector:some-user-name"}, 694 }, 695 }) 696 fakeTeam2.AuthReturns(atc.TeamAuth{ 697 "member": map[string][]string{ 698 "users": {"some-connector:some-user-name"}, 699 }, 700 }) 701 fakeTeam3.AuthReturns(atc.TeamAuth{ 702 "viewer": map[string][]string{ 703 "users": {"some-connector:some-user-name"}, 704 }, 705 }) 706 }) 707 708 It("returns result with teams", func() { 709 Expect(result["some-team-1"]).To(ContainElement("owner")) 710 Expect(result["some-team-2"]).To(ContainElement("member")) 711 Expect(result["some-team-3"]).To(ContainElement("viewer")) 712 }) 713 }) 714 715 Context("when the user is granted a role from a group", func() { 716 BeforeEach(func() { 717 fakeTeam1.AuthReturns(atc.TeamAuth{ 718 "owner": map[string][]string{ 719 "groups": {"some-connector:some-group"}, 720 }, 721 }) 722 fakeTeam2.AuthReturns(atc.TeamAuth{ 723 "member": map[string][]string{ 724 "groups": {"some-connector:some-group"}, 725 }, 726 }) 727 fakeTeam3.AuthReturns(atc.TeamAuth{ 728 "viewer": map[string][]string{ 729 "groups": {"some-connector:some-group"}, 730 }, 731 }) 732 }) 733 734 It("returns result with teams", func() { 735 Expect(result["some-team-1"]).To(ContainElement("owner")) 736 Expect(result["some-team-2"]).To(ContainElement("member")) 737 Expect(result["some-team-3"]).To(ContainElement("viewer")) 738 }) 739 }) 740 741 Context("when the user is granted multiple roles on the same team", func() { 742 BeforeEach(func() { 743 fakeTeam1.AuthReturns(atc.TeamAuth{ 744 "owner": map[string][]string{ 745 "users": {"some-connector:some-user-id"}, 746 }, 747 "member": map[string][]string{ 748 "groups": {"some-connector:some-group"}, 749 }, 750 }) 751 }) 752 753 It("adds both roles", func() { 754 Expect(result["some-team-1"]).To(ContainElement("owner")) 755 Expect(result["some-team-1"]).To(ContainElement("member")) 756 }) 757 }) 758 759 Context("when the user is granted the same role multiple times", func() { 760 BeforeEach(func() { 761 fakeTeam1.AuthReturns(atc.TeamAuth{ 762 "owner": map[string][]string{ 763 "users": {"some-connector:some-user-id"}, 764 "groups": {"some-connector:some-group"}, 765 }, 766 }) 767 }) 768 769 It("only adds the role once", func() { 770 Expect(result["some-team-1"]).To(ContainElement("owner")) 771 }) 772 }) 773 }) 774 }) 775 })