github.com/gravitational/teleport/api@v0.0.0-20240507183017-3110591cbafc/types/provisioning_test.go (about) 1 /* 2 Copyright 2022 Gravitational, Inc. 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 types 18 19 import ( 20 "testing" 21 "time" 22 23 "github.com/gravitational/trace" 24 "github.com/stretchr/testify/require" 25 26 "github.com/gravitational/teleport/api/defaults" 27 "github.com/gravitational/teleport/api/fixtures" 28 ) 29 30 func TestProvisionTokenV2_CheckAndSetDefaults(t *testing.T) { 31 testcases := []struct { 32 desc string 33 token *ProvisionTokenV2 34 expected *ProvisionTokenV2 35 wantErr bool 36 }{ 37 { 38 desc: "empty", 39 token: &ProvisionTokenV2{}, 40 wantErr: true, 41 }, 42 { 43 desc: "missing roles", 44 token: &ProvisionTokenV2{ 45 Metadata: Metadata{ 46 Name: "test", 47 }, 48 }, 49 wantErr: true, 50 }, 51 { 52 desc: "invalid role", 53 token: &ProvisionTokenV2{ 54 Metadata: Metadata{ 55 Name: "test", 56 }, 57 Spec: ProvisionTokenSpecV2{ 58 Roles: []SystemRole{RoleNode, "not a role"}, 59 }, 60 }, 61 wantErr: true, 62 }, 63 { 64 desc: "simple token", 65 token: &ProvisionTokenV2{ 66 Metadata: Metadata{ 67 Name: "test", 68 }, 69 Spec: ProvisionTokenSpecV2{ 70 Roles: []SystemRole{RoleNode}, 71 }, 72 }, 73 expected: &ProvisionTokenV2{ 74 Kind: "token", 75 Version: "v2", 76 Metadata: Metadata{ 77 Name: "test", 78 Namespace: "default", 79 }, 80 Spec: ProvisionTokenSpecV2{ 81 Roles: []SystemRole{RoleNode}, 82 JoinMethod: "token", 83 }, 84 }, 85 }, 86 { 87 desc: "implicit ec2 method", 88 token: &ProvisionTokenV2{ 89 Metadata: Metadata{ 90 Name: "test", 91 }, 92 Spec: ProvisionTokenSpecV2{ 93 Roles: []SystemRole{RoleNode}, 94 Allow: []*TokenRule{ 95 { 96 AWSAccount: "1234", 97 AWSRole: "1234/role", 98 AWSRegions: []string{"us-west-2"}, 99 }, 100 }, 101 }, 102 }, 103 expected: &ProvisionTokenV2{ 104 Kind: "token", 105 Version: "v2", 106 Metadata: Metadata{ 107 Name: "test", 108 Namespace: "default", 109 }, 110 Spec: ProvisionTokenSpecV2{ 111 Roles: []SystemRole{RoleNode}, 112 JoinMethod: "ec2", 113 Allow: []*TokenRule{ 114 { 115 AWSAccount: "1234", 116 AWSRole: "1234/role", 117 AWSRegions: []string{"us-west-2"}, 118 }, 119 }, 120 AWSIIDTTL: Duration(5 * time.Minute), 121 }, 122 }, 123 }, 124 { 125 desc: "explicit ec2 method", 126 token: &ProvisionTokenV2{ 127 Metadata: Metadata{ 128 Name: "test", 129 }, 130 Spec: ProvisionTokenSpecV2{ 131 Roles: []SystemRole{RoleNode}, 132 JoinMethod: "ec2", 133 Allow: []*TokenRule{{AWSAccount: "1234"}}, 134 }, 135 }, 136 expected: &ProvisionTokenV2{ 137 Kind: "token", 138 Version: "v2", 139 Metadata: Metadata{ 140 Name: "test", 141 Namespace: "default", 142 }, 143 Spec: ProvisionTokenSpecV2{ 144 Roles: []SystemRole{RoleNode}, 145 JoinMethod: "ec2", 146 Allow: []*TokenRule{{AWSAccount: "1234"}}, 147 AWSIIDTTL: Duration(5 * time.Minute), 148 }, 149 }, 150 }, 151 { 152 desc: "ec2 method no allow rules", 153 token: &ProvisionTokenV2{ 154 Metadata: Metadata{ 155 Name: "test", 156 }, 157 Spec: ProvisionTokenSpecV2{ 158 Roles: []SystemRole{RoleNode}, 159 JoinMethod: "ec2", 160 }, 161 }, 162 wantErr: true, 163 }, 164 { 165 desc: "ec2 method with aws_arn", 166 token: &ProvisionTokenV2{ 167 Metadata: Metadata{ 168 Name: "test", 169 }, 170 Spec: ProvisionTokenSpecV2{ 171 Roles: []SystemRole{RoleNode}, 172 JoinMethod: "ec2", 173 Allow: []*TokenRule{ 174 { 175 AWSAccount: "1234", 176 AWSARN: "1234", 177 }, 178 }, 179 }, 180 }, 181 wantErr: true, 182 }, 183 { 184 desc: "ec2 method empty rule", 185 token: &ProvisionTokenV2{ 186 Metadata: Metadata{ 187 Name: "test", 188 }, 189 Spec: ProvisionTokenSpecV2{ 190 Roles: []SystemRole{RoleNode}, 191 JoinMethod: "ec2", 192 Allow: []*TokenRule{{}}, 193 }, 194 }, 195 wantErr: true, 196 }, 197 { 198 desc: "iam method", 199 token: &ProvisionTokenV2{ 200 Metadata: Metadata{ 201 Name: "test", 202 }, 203 Spec: ProvisionTokenSpecV2{ 204 Roles: []SystemRole{RoleNode}, 205 JoinMethod: "ec2", 206 Allow: []*TokenRule{{AWSAccount: "1234"}}, 207 }, 208 }, 209 expected: &ProvisionTokenV2{ 210 Kind: "token", 211 Version: "v2", 212 Metadata: Metadata{ 213 Name: "test", 214 Namespace: "default", 215 }, 216 Spec: ProvisionTokenSpecV2{ 217 Roles: []SystemRole{RoleNode}, 218 JoinMethod: "ec2", 219 Allow: []*TokenRule{{AWSAccount: "1234"}}, 220 AWSIIDTTL: Duration(5 * time.Minute), 221 }, 222 }, 223 }, 224 { 225 desc: "iam method with aws_role", 226 token: &ProvisionTokenV2{ 227 Metadata: Metadata{ 228 Name: "test", 229 }, 230 Spec: ProvisionTokenSpecV2{ 231 Roles: []SystemRole{RoleNode}, 232 JoinMethod: "iam", 233 Allow: []*TokenRule{ 234 { 235 AWSAccount: "1234", 236 AWSRole: "1234/role", 237 }, 238 }, 239 }, 240 }, 241 wantErr: true, 242 }, 243 { 244 desc: "iam method with aws_regions", 245 token: &ProvisionTokenV2{ 246 Metadata: Metadata{ 247 Name: "test", 248 }, 249 Spec: ProvisionTokenSpecV2{ 250 Roles: []SystemRole{RoleNode}, 251 JoinMethod: "iam", 252 Allow: []*TokenRule{ 253 { 254 AWSAccount: "1234", 255 AWSRegions: []string{"us-west-2"}, 256 }, 257 }, 258 }, 259 }, 260 wantErr: true, 261 }, 262 { 263 desc: "github valid", 264 token: &ProvisionTokenV2{ 265 Metadata: Metadata{ 266 Name: "test", 267 }, 268 Spec: ProvisionTokenSpecV2{ 269 Roles: []SystemRole{RoleNode}, 270 JoinMethod: JoinMethodGitHub, 271 GitHub: &ProvisionTokenSpecV2GitHub{ 272 Allow: []*ProvisionTokenSpecV2GitHub_Rule{ 273 { 274 Sub: "foo", 275 }, 276 }, 277 }, 278 }, 279 }, 280 }, 281 { 282 desc: "github ghes valid", 283 token: &ProvisionTokenV2{ 284 Metadata: Metadata{ 285 Name: "test", 286 }, 287 Spec: ProvisionTokenSpecV2{ 288 Roles: []SystemRole{RoleNode}, 289 JoinMethod: JoinMethodGitHub, 290 GitHub: &ProvisionTokenSpecV2GitHub{ 291 EnterpriseServerHost: "example.com", 292 Allow: []*ProvisionTokenSpecV2GitHub_Rule{ 293 { 294 Sub: "foo", 295 }, 296 }, 297 }, 298 }, 299 }, 300 }, 301 { 302 desc: "github ghes invalid", 303 token: &ProvisionTokenV2{ 304 Metadata: Metadata{ 305 Name: "test", 306 }, 307 Spec: ProvisionTokenSpecV2{ 308 Roles: []SystemRole{RoleNode}, 309 JoinMethod: JoinMethodGitHub, 310 GitHub: &ProvisionTokenSpecV2GitHub{ 311 EnterpriseServerHost: "https://example.com", 312 Allow: []*ProvisionTokenSpecV2GitHub_Rule{ 313 { 314 Sub: "foo", 315 }, 316 }, 317 }, 318 }, 319 }, 320 wantErr: true, 321 }, 322 { 323 desc: "github slug and ghes set", 324 token: &ProvisionTokenV2{ 325 Metadata: Metadata{ 326 Name: "test", 327 }, 328 Spec: ProvisionTokenSpecV2{ 329 Roles: []SystemRole{RoleNode}, 330 JoinMethod: JoinMethodGitHub, 331 GitHub: &ProvisionTokenSpecV2GitHub{ 332 EnterpriseServerHost: "example.com", 333 EnterpriseSlug: "slug", 334 Allow: []*ProvisionTokenSpecV2GitHub_Rule{ 335 { 336 Sub: "foo", 337 }, 338 }, 339 }, 340 }, 341 }, 342 wantErr: true, 343 }, 344 { 345 desc: "circleci valid", 346 token: &ProvisionTokenV2{ 347 Metadata: Metadata{ 348 Name: "test", 349 }, 350 Spec: ProvisionTokenSpecV2{ 351 Roles: []SystemRole{RoleNode}, 352 JoinMethod: JoinMethodCircleCI, 353 CircleCI: &ProvisionTokenSpecV2CircleCI{ 354 OrganizationID: "foo", 355 Allow: []*ProvisionTokenSpecV2CircleCI_Rule{ 356 { 357 ProjectID: "foo", 358 ContextID: "bar", 359 }, 360 }, 361 }, 362 }, 363 }, 364 }, 365 { 366 desc: "circleci and no allow", 367 token: &ProvisionTokenV2{ 368 Metadata: Metadata{ 369 Name: "test", 370 }, 371 Spec: ProvisionTokenSpecV2{ 372 Roles: []SystemRole{RoleNode}, 373 JoinMethod: JoinMethodCircleCI, 374 CircleCI: &ProvisionTokenSpecV2CircleCI{ 375 OrganizationID: "foo", 376 }, 377 }, 378 }, 379 wantErr: true, 380 }, 381 { 382 desc: "circleci and no org id", 383 token: &ProvisionTokenV2{ 384 Metadata: Metadata{ 385 Name: "test", 386 }, 387 Spec: ProvisionTokenSpecV2{ 388 Roles: []SystemRole{RoleNode}, 389 JoinMethod: JoinMethodCircleCI, 390 CircleCI: &ProvisionTokenSpecV2CircleCI{ 391 Allow: []*ProvisionTokenSpecV2CircleCI_Rule{ 392 { 393 ProjectID: "foo", 394 }, 395 }, 396 }, 397 }, 398 }, 399 wantErr: true, 400 }, 401 { 402 desc: "circleci allow rule blank", 403 token: &ProvisionTokenV2{ 404 Metadata: Metadata{ 405 Name: "test", 406 }, 407 Spec: ProvisionTokenSpecV2{ 408 Roles: []SystemRole{RoleNode}, 409 JoinMethod: JoinMethodCircleCI, 410 CircleCI: &ProvisionTokenSpecV2CircleCI{ 411 Allow: []*ProvisionTokenSpecV2CircleCI_Rule{ 412 {}, 413 }, 414 }, 415 }, 416 }, 417 wantErr: true, 418 }, 419 { 420 desc: "kubernetes: in_cluster defaults", 421 token: &ProvisionTokenV2{ 422 Metadata: Metadata{ 423 Name: "test", 424 }, 425 Spec: ProvisionTokenSpecV2{ 426 Roles: []SystemRole{RoleNode}, 427 JoinMethod: JoinMethodKubernetes, 428 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 429 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 430 { 431 ServiceAccount: "namespace:my-service-account", 432 }, 433 }, 434 }, 435 }, 436 }, 437 expected: &ProvisionTokenV2{ 438 Kind: "token", 439 Version: "v2", 440 Metadata: Metadata{ 441 Name: "test", 442 Namespace: "default", 443 }, 444 Spec: ProvisionTokenSpecV2{ 445 Roles: []SystemRole{RoleNode}, 446 JoinMethod: JoinMethodKubernetes, 447 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 448 Type: KubernetesJoinTypeInCluster, 449 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 450 { 451 ServiceAccount: "namespace:my-service-account", 452 }, 453 }, 454 }, 455 }, 456 }, 457 }, 458 { 459 desc: "kubernetes: valid in_cluster", 460 token: &ProvisionTokenV2{ 461 Metadata: Metadata{ 462 Name: "test", 463 }, 464 Spec: ProvisionTokenSpecV2{ 465 Roles: []SystemRole{RoleNode}, 466 JoinMethod: JoinMethodKubernetes, 467 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 468 Type: KubernetesJoinTypeInCluster, 469 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 470 { 471 ServiceAccount: "namespace:my-service-account", 472 }, 473 }, 474 }, 475 }, 476 }, 477 }, 478 { 479 desc: "kubernetes: valid static_jwks", 480 token: &ProvisionTokenV2{ 481 Metadata: Metadata{ 482 Name: "test", 483 }, 484 Spec: ProvisionTokenSpecV2{ 485 Roles: []SystemRole{RoleNode}, 486 JoinMethod: JoinMethodKubernetes, 487 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 488 Type: KubernetesJoinTypeStaticJWKS, 489 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 490 { 491 ServiceAccount: "namespace:my-service-account", 492 }, 493 }, 494 StaticJWKS: &ProvisionTokenSpecV2Kubernetes_StaticJWKSConfig{ 495 JWKS: `{"keys":[{"use":"sig","kty":"RSA","kid":"-snip-","alg":"RS256","n":"-snip-","e":"-snip-"}]}`, 496 }, 497 }, 498 }, 499 }, 500 }, 501 { 502 desc: "kubernetes: missing static_jwks", 503 token: &ProvisionTokenV2{ 504 Metadata: Metadata{ 505 Name: "test", 506 }, 507 Spec: ProvisionTokenSpecV2{ 508 Roles: []SystemRole{RoleNode}, 509 JoinMethod: JoinMethodKubernetes, 510 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 511 Type: KubernetesJoinTypeStaticJWKS, 512 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 513 { 514 ServiceAccount: "namespace:my-service-account", 515 }, 516 }, 517 }, 518 }, 519 }, 520 wantErr: true, 521 }, 522 { 523 desc: "kubernetes: missing static_jwks.jwks", 524 token: &ProvisionTokenV2{ 525 Metadata: Metadata{ 526 Name: "test", 527 }, 528 Spec: ProvisionTokenSpecV2{ 529 Roles: []SystemRole{RoleNode}, 530 JoinMethod: JoinMethodKubernetes, 531 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 532 Type: KubernetesJoinTypeStaticJWKS, 533 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 534 { 535 ServiceAccount: "namespace:my-service-account", 536 }, 537 }, 538 StaticJWKS: &ProvisionTokenSpecV2Kubernetes_StaticJWKSConfig{}, 539 }, 540 }, 541 }, 542 wantErr: true, 543 }, 544 { 545 desc: "kubernetes: wrong service account name", 546 token: &ProvisionTokenV2{ 547 Metadata: Metadata{ 548 Name: "test", 549 }, 550 Spec: ProvisionTokenSpecV2{ 551 Roles: []SystemRole{RoleNode}, 552 JoinMethod: JoinMethodKubernetes, 553 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 554 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 555 { 556 ServiceAccount: "my-service-account", 557 }, 558 }, 559 }, 560 }, 561 }, 562 wantErr: true, 563 }, 564 { 565 desc: "kubernetes: allow rule blank", 566 token: &ProvisionTokenV2{ 567 Metadata: Metadata{ 568 Name: "test", 569 }, 570 Spec: ProvisionTokenSpecV2{ 571 Roles: []SystemRole{RoleNode}, 572 JoinMethod: JoinMethodKubernetes, 573 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 574 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 575 {}, 576 }, 577 }, 578 }, 579 }, 580 wantErr: true, 581 }, 582 { 583 desc: "gitlab empty allow rules", 584 token: &ProvisionTokenV2{ 585 Metadata: Metadata{ 586 Name: "test", 587 }, 588 Spec: ProvisionTokenSpecV2{ 589 Roles: []SystemRole{RoleNode}, 590 JoinMethod: JoinMethodGitLab, 591 GitLab: &ProvisionTokenSpecV2GitLab{ 592 Allow: []*ProvisionTokenSpecV2GitLab_Rule{}, 593 }, 594 }, 595 }, 596 wantErr: true, 597 }, 598 { 599 desc: "gitlab missing config", 600 token: &ProvisionTokenV2{ 601 Metadata: Metadata{ 602 Name: "test", 603 }, 604 Spec: ProvisionTokenSpecV2{ 605 Roles: []SystemRole{RoleNode}, 606 JoinMethod: JoinMethodGitLab, 607 GitLab: nil, 608 }, 609 }, 610 wantErr: true, 611 }, 612 { 613 desc: "gitlab empty allow rule", 614 token: &ProvisionTokenV2{ 615 Metadata: Metadata{ 616 Name: "test", 617 }, 618 Spec: ProvisionTokenSpecV2{ 619 Roles: []SystemRole{RoleNode}, 620 JoinMethod: JoinMethodGitLab, 621 GitLab: &ProvisionTokenSpecV2GitLab{ 622 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 623 {}, 624 }, 625 }, 626 }, 627 }, 628 wantErr: true, 629 }, 630 { 631 desc: "gitlab defaults", 632 token: &ProvisionTokenV2{ 633 Metadata: Metadata{ 634 Name: "test", 635 }, 636 Spec: ProvisionTokenSpecV2{ 637 Roles: []SystemRole{RoleNode}, 638 JoinMethod: JoinMethodGitLab, 639 GitLab: &ProvisionTokenSpecV2GitLab{ 640 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 641 { 642 Sub: "asub", 643 }, 644 }, 645 }, 646 }, 647 }, 648 expected: &ProvisionTokenV2{ 649 Kind: KindToken, 650 Version: V2, 651 Metadata: Metadata{ 652 Name: "test", 653 Namespace: defaults.Namespace, 654 }, 655 Spec: ProvisionTokenSpecV2{ 656 Roles: []SystemRole{RoleNode}, 657 JoinMethod: JoinMethodGitLab, 658 GitLab: &ProvisionTokenSpecV2GitLab{ 659 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 660 { 661 Sub: "asub", 662 }, 663 }, 664 Domain: defaultGitLabDomain, 665 }, 666 }, 667 }, 668 }, 669 { 670 desc: "overridden domain", 671 token: &ProvisionTokenV2{ 672 Metadata: Metadata{ 673 Name: "test", 674 }, 675 Spec: ProvisionTokenSpecV2{ 676 Roles: []SystemRole{RoleNode}, 677 JoinMethod: JoinMethodGitLab, 678 GitLab: &ProvisionTokenSpecV2GitLab{ 679 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 680 { 681 Sub: "asub", 682 }, 683 }, 684 Domain: "gitlab.example.com", 685 }, 686 }, 687 }, 688 expected: &ProvisionTokenV2{ 689 Kind: KindToken, 690 Version: V2, 691 Metadata: Metadata{ 692 Name: "test", 693 Namespace: defaults.Namespace, 694 }, 695 Spec: ProvisionTokenSpecV2{ 696 Roles: []SystemRole{RoleNode}, 697 JoinMethod: JoinMethodGitLab, 698 GitLab: &ProvisionTokenSpecV2GitLab{ 699 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 700 { 701 Sub: "asub", 702 }, 703 }, 704 Domain: "gitlab.example.com", 705 }, 706 }, 707 }, 708 }, 709 { 710 desc: "invalid overridden domain", 711 token: &ProvisionTokenV2{ 712 Metadata: Metadata{ 713 Name: "test", 714 }, 715 Spec: ProvisionTokenSpecV2{ 716 Roles: []SystemRole{RoleNode}, 717 JoinMethod: JoinMethodGitLab, 718 GitLab: &ProvisionTokenSpecV2GitLab{ 719 Allow: []*ProvisionTokenSpecV2GitLab_Rule{ 720 { 721 Sub: "asub", 722 }, 723 }, 724 Domain: "http://gitlab.example.com", 725 }, 726 }, 727 }, 728 wantErr: true, 729 }, 730 { 731 desc: "spacelift", 732 token: &ProvisionTokenV2{ 733 Metadata: Metadata{ 734 Name: "test", 735 }, 736 Spec: ProvisionTokenSpecV2{ 737 Roles: []SystemRole{RoleNode}, 738 JoinMethod: JoinMethodSpacelift, 739 Spacelift: &ProvisionTokenSpecV2Spacelift{ 740 Hostname: "example.app.spacelift.io", 741 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{ 742 { 743 SpaceID: "foo", 744 }, 745 }, 746 }, 747 }, 748 }, 749 expected: &ProvisionTokenV2{ 750 Kind: "token", 751 Version: "v2", 752 Metadata: Metadata{ 753 Name: "test", 754 Namespace: "default", 755 }, 756 Spec: ProvisionTokenSpecV2{ 757 Roles: []SystemRole{RoleNode}, 758 JoinMethod: JoinMethodSpacelift, 759 Spacelift: &ProvisionTokenSpecV2Spacelift{ 760 Hostname: "example.app.spacelift.io", 761 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{ 762 { 763 SpaceID: "foo", 764 }, 765 }, 766 }, 767 }, 768 }, 769 }, 770 { 771 desc: "spacelift empty allow rules", 772 token: &ProvisionTokenV2{ 773 Metadata: Metadata{ 774 Name: "test", 775 }, 776 Spec: ProvisionTokenSpecV2{ 777 Roles: []SystemRole{RoleNode}, 778 JoinMethod: JoinMethodSpacelift, 779 Spacelift: &ProvisionTokenSpecV2Spacelift{ 780 Hostname: "example.app.spacelift.io", 781 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{}, 782 }, 783 }, 784 }, 785 wantErr: true, 786 }, 787 { 788 desc: "spacelift rule missing fields", 789 token: &ProvisionTokenV2{ 790 Metadata: Metadata{ 791 Name: "test", 792 }, 793 Spec: ProvisionTokenSpecV2{ 794 Roles: []SystemRole{RoleNode}, 795 JoinMethod: JoinMethodSpacelift, 796 Spacelift: &ProvisionTokenSpecV2Spacelift{ 797 Hostname: "example.app.spacelift.io", 798 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{{}}, 799 }, 800 }, 801 }, 802 wantErr: true, 803 }, 804 { 805 desc: "spacelift missing hostname", 806 token: &ProvisionTokenV2{ 807 Metadata: Metadata{ 808 Name: "test", 809 }, 810 Spec: ProvisionTokenSpecV2{ 811 Roles: []SystemRole{RoleNode}, 812 JoinMethod: JoinMethodSpacelift, 813 Spacelift: &ProvisionTokenSpecV2Spacelift{ 814 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{ 815 { 816 SpaceID: "foo", 817 }, 818 }, 819 }, 820 }, 821 }, 822 wantErr: true, 823 }, 824 { 825 desc: "spacelift incorrect hostname", 826 token: &ProvisionTokenV2{ 827 Metadata: Metadata{ 828 Name: "test", 829 }, 830 Spec: ProvisionTokenSpecV2{ 831 Roles: []SystemRole{RoleNode}, 832 JoinMethod: JoinMethodSpacelift, 833 Spacelift: &ProvisionTokenSpecV2Spacelift{ 834 Hostname: "https://example.app.spacelift.io", 835 Allow: []*ProvisionTokenSpecV2Spacelift_Rule{ 836 { 837 SpaceID: "foo", 838 }, 839 }, 840 }, 841 }, 842 }, 843 wantErr: true, 844 }, 845 { 846 desc: "gcp method", 847 token: &ProvisionTokenV2{ 848 Metadata: Metadata{ 849 Name: "test", 850 }, 851 Spec: ProvisionTokenSpecV2{ 852 Roles: []SystemRole{RoleNode}, 853 JoinMethod: "gcp", 854 GCP: &ProvisionTokenSpecV2GCP{ 855 Allow: []*ProvisionTokenSpecV2GCP_Rule{ 856 { 857 ProjectIDs: []string{"p1"}, 858 Locations: []string{"us-west1-b"}, 859 }, 860 }, 861 }, 862 }, 863 }, 864 expected: &ProvisionTokenV2{ 865 Kind: "token", 866 Version: "v2", 867 Metadata: Metadata{ 868 Name: "test", 869 Namespace: "default", 870 }, 871 Spec: ProvisionTokenSpecV2{ 872 Roles: []SystemRole{RoleNode}, 873 JoinMethod: "gcp", 874 GCP: &ProvisionTokenSpecV2GCP{ 875 Allow: []*ProvisionTokenSpecV2GCP_Rule{ 876 { 877 ProjectIDs: []string{"p1"}, 878 Locations: []string{"us-west1-b"}, 879 }, 880 }, 881 }, 882 }, 883 }, 884 }, 885 { 886 desc: "gcp method no project ids", 887 token: &ProvisionTokenV2{ 888 Metadata: Metadata{ 889 Name: "test", 890 }, 891 Spec: ProvisionTokenSpecV2{ 892 Roles: []SystemRole{RoleNode}, 893 JoinMethod: "gcp", 894 GCP: &ProvisionTokenSpecV2GCP{ 895 Allow: []*ProvisionTokenSpecV2GCP_Rule{ 896 { 897 Locations: []string{"us-west1-b"}, 898 }, 899 }, 900 }, 901 }, 902 }, 903 wantErr: true, 904 }, 905 { 906 desc: "tpm success with CA", 907 token: &ProvisionTokenV2{ 908 Metadata: Metadata{ 909 Name: "test", 910 }, 911 Spec: ProvisionTokenSpecV2{ 912 Roles: []SystemRole{RoleNode}, 913 JoinMethod: JoinMethodTPM, 914 TPM: &ProvisionTokenSpecV2TPM{ 915 EKCertAllowedCAs: []string{fixtures.TLSCACertPEM}, 916 Allow: []*ProvisionTokenSpecV2TPM_Rule{ 917 { 918 Description: "my description", 919 EKPublicHash: "d4b45864d9d6fabfc568d74f26c35ababde2105337d7af9a6605e1c56c891aa6", 920 }, 921 { 922 EKCertificateSerial: "73:df:dc:bd:af:ef:8a:d8:15:2e:96:71:7a:3e:7f:a4", 923 }, 924 { 925 EKPublicHash: "d4b45864d9d6fabfc568d74f26c35ababde2105337d7af9a6605e1c56c891aa6", 926 EKCertificateSerial: "73:df:dc:bd:af:ef:8a:d8:15:2e:96:71:7a:3e:7f:a4", 927 }, 928 }, 929 }, 930 }, 931 }, 932 wantErr: false, 933 }, 934 { 935 desc: "tpm success without CA", 936 token: &ProvisionTokenV2{ 937 Metadata: Metadata{ 938 Name: "test", 939 }, 940 Spec: ProvisionTokenSpecV2{ 941 Roles: []SystemRole{RoleNode}, 942 JoinMethod: JoinMethodTPM, 943 TPM: &ProvisionTokenSpecV2TPM{ 944 Allow: []*ProvisionTokenSpecV2TPM_Rule{ 945 { 946 Description: "my description", 947 EKPublicHash: "d4b45864d9d6fabfc568d74f26c35ababde2105337d7af9a6605e1c56c891aa6", 948 }, 949 { 950 EKCertificateSerial: "73:df:dc:bd:af:ef:8a:d8:15:2e:96:71:7a:3e:7f:a4", 951 }, 952 { 953 EKPublicHash: "d4b45864d9d6fabfc568d74f26c35ababde2105337d7af9a6605e1c56c891aa6", 954 EKCertificateSerial: "73:df:dc:bd:af:ef:8a:d8:15:2e:96:71:7a:3e:7f:a4", 955 }, 956 }, 957 }, 958 }, 959 }, 960 wantErr: false, 961 }, 962 { 963 desc: "tpm corrupt CA", 964 token: &ProvisionTokenV2{ 965 Metadata: Metadata{ 966 Name: "test", 967 }, 968 Spec: ProvisionTokenSpecV2{ 969 Roles: []SystemRole{RoleNode}, 970 JoinMethod: JoinMethodTPM, 971 TPM: &ProvisionTokenSpecV2TPM{ 972 EKCertAllowedCAs: []string{"corrupt"}, 973 Allow: []*ProvisionTokenSpecV2TPM_Rule{ 974 { 975 Description: "my description", 976 EKPublicHash: "d4b45864d9d6fabfc568d74f26c35ababde2105337d7af9a6605e1c56c891aa6", 977 }, 978 }, 979 }, 980 }, 981 }, 982 wantErr: true, 983 }, 984 { 985 desc: "tpm missing rules", 986 token: &ProvisionTokenV2{ 987 Metadata: Metadata{ 988 Name: "test", 989 }, 990 Spec: ProvisionTokenSpecV2{ 991 Roles: []SystemRole{RoleNode}, 992 JoinMethod: JoinMethodTPM, 993 TPM: &ProvisionTokenSpecV2TPM{ 994 EKCertAllowedCAs: []string{}, 995 Allow: []*ProvisionTokenSpecV2TPM_Rule{}, 996 }, 997 }, 998 }, 999 wantErr: true, 1000 }, 1001 { 1002 desc: "tpm rule without ekpubhash or ekcertserial", 1003 token: &ProvisionTokenV2{ 1004 Metadata: Metadata{ 1005 Name: "test", 1006 }, 1007 Spec: ProvisionTokenSpecV2{ 1008 Roles: []SystemRole{RoleNode}, 1009 JoinMethod: JoinMethodTPM, 1010 TPM: &ProvisionTokenSpecV2TPM{ 1011 EKCertAllowedCAs: []string{}, 1012 Allow: []*ProvisionTokenSpecV2TPM_Rule{ 1013 { 1014 Description: "my description", 1015 }, 1016 }, 1017 }, 1018 }, 1019 }, 1020 wantErr: true, 1021 }, 1022 } 1023 1024 for _, tc := range testcases { 1025 t.Run(tc.desc, func(t *testing.T) { 1026 err := tc.token.CheckAndSetDefaults() 1027 if tc.wantErr { 1028 require.Error(t, err) 1029 require.True(t, 1030 trace.IsBadParameter(err), 1031 "want BadParameter, got %v (%T)", err, trace.Unwrap(err)) 1032 return 1033 } 1034 require.NoError(t, err) 1035 1036 if tc.expected != nil { 1037 require.Equal(t, tc.expected, tc.token) 1038 } 1039 }) 1040 } 1041 } 1042 1043 func TestProvisionTokenV2_GetSafeName(t *testing.T) { 1044 t.Run("token join method (short)", func(t *testing.T) { 1045 tok, err := NewProvisionToken("1234", []SystemRole{RoleNode}, time.Now()) 1046 require.NoError(t, err) 1047 got := tok.GetSafeName() 1048 require.Equal(t, "****", got) 1049 }) 1050 t.Run("token join method (long)", func(t *testing.T) { 1051 tok, err := NewProvisionToken("0123456789abcdef", []SystemRole{RoleNode}, time.Now()) 1052 require.NoError(t, err) 1053 got := tok.GetSafeName() 1054 require.Equal(t, "************cdef", got) 1055 }) 1056 t.Run("non-token join method", func(t *testing.T) { 1057 tok, err := NewProvisionTokenFromSpec("12345678", time.Now(), ProvisionTokenSpecV2{ 1058 Roles: []SystemRole{RoleNode}, 1059 JoinMethod: JoinMethodKubernetes, 1060 Kubernetes: &ProvisionTokenSpecV2Kubernetes{ 1061 Allow: []*ProvisionTokenSpecV2Kubernetes_Rule{ 1062 { 1063 ServiceAccount: "namespace:my-service-account", 1064 }, 1065 }, 1066 }, 1067 }) 1068 require.NoError(t, err) 1069 got := tok.GetSafeName() 1070 require.Equal(t, "12345678", got) 1071 }) 1072 } 1073 1074 func TestProvisionTokenV2_CaseInsensitiveRoles(t *testing.T) { 1075 t.Parallel() 1076 t.Run("via constructor", func(t *testing.T) { 1077 tok, err := NewProvisionToken("token", SystemRoles{"nOde", "AuTh"}, time.Now()) 1078 require.NoError(t, err) 1079 require.Equal(t, SystemRoles{RoleNode, RoleAuth}, tok.GetRoles()) 1080 }) 1081 t.Run("via struct", func(t *testing.T) { 1082 tok := &ProvisionTokenV2{ 1083 Spec: ProvisionTokenSpecV2{ 1084 Roles: []SystemRole{"nOdE", "AuTh"}, 1085 }, 1086 } 1087 require.Equal(t, SystemRoles{RoleNode, RoleAuth}, tok.GetRoles()) 1088 }) 1089 } 1090 1091 func TestProvisionTokenV2_SignupRole(t *testing.T) { 1092 t.Parallel() 1093 tok, err := NewProvisionToken("token", SystemRoles{RoleSignup}, time.Now()) 1094 require.NoError(t, err) 1095 require.Equal(t, SystemRoles{RoleSignup}, tok.GetRoles()) 1096 }