77 "net"
88 "net/http"
99 "net/http/httptest"
10+ "strings"
1011 "testing"
1112
1213 "github.com/openshift/backplane-cli/pkg/awsutil"
@@ -15,6 +16,7 @@ import (
1516 "github.com/aws/aws-sdk-go-v2/credentials"
1617 "github.com/aws/aws-sdk-go-v2/credentials/stscreds"
1718 "github.com/aws/aws-sdk-go-v2/service/sts"
19+ "github.com/aws/aws-sdk-go-v2/service/sts/types"
1820 "github.com/golang/mock/gomock"
1921 . "github.com/onsi/ginkgo/v2"
2022 . "github.com/onsi/gomega"
@@ -523,3 +525,313 @@ var _ = Describe("isIsolatedBackplaneAccess", func() {
523525 })
524526 })
525527})
528+
529+ var _ = Describe ("PolicyARNs Integration" , func () {
530+ var (
531+ testSessionPolicyArn string
532+ )
533+
534+ BeforeEach (func () {
535+ testSessionPolicyArn = "arn:aws:iam::123456789012:policy/TestSessionPolicy"
536+ })
537+
538+ // Helper function to simulate the getIsolatedCredentials logic
539+ simulateGetIsolatedCredentialsLogic := func (roleChainResponse assumeChainResponse ) []awsutil.RoleArnSession {
540+ assumeRoleArnSessionSequence := make ([]awsutil.RoleArnSession , 0 , len (roleChainResponse .AssumptionSequence ))
541+ for _ , namedRoleArnEntry := range roleChainResponse .AssumptionSequence {
542+ roleArnSession := awsutil.RoleArnSession {RoleArn : namedRoleArnEntry .Arn }
543+ if namedRoleArnEntry .Name == CustomerRoleArnName || namedRoleArnEntry .Name == OrgRoleArnName {
544+ roleArnSession .RoleSessionName = roleChainResponse .CustomerRoleSessionName
545+ } else {
546+ roleArnSession .RoleSessionName = "test@example.com"
547+ }
548+
549+ // Default to no policy ARNs
550+ roleArnSession .PolicyARNs = []types.PolicyDescriptorType {}
551+ if namedRoleArnEntry .Name == CustomerRoleArnName {
552+ roleArnSession .IsCustomerRole = true
553+ // Add the session policy ARN for selected roles
554+ if roleChainResponse .SessionPolicyArn != "" {
555+ roleArnSession .PolicyARNs = []types.PolicyDescriptorType {
556+ {
557+ Arn : aws .String (roleChainResponse .SessionPolicyArn ),
558+ },
559+ }
560+ }
561+ } else {
562+ roleArnSession .IsCustomerRole = false
563+ }
564+ roleArnSession .Name = namedRoleArnEntry .Name
565+
566+ assumeRoleArnSessionSequence = append (assumeRoleArnSessionSequence , roleArnSession )
567+ }
568+ return assumeRoleArnSessionSequence
569+ }
570+
571+ // Generated by Cursor
572+ Context ("when creating RoleArnSession with SessionPolicyArn" , func () {
573+ It ("should set PolicyARNs for customer roles" , func () {
574+ roleChainResponse := assumeChainResponse {
575+ AssumptionSequence : []namedRoleArn {
576+ {
577+ Name : CustomerRoleArnName ,
578+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
579+ },
580+ },
581+ CustomerRoleSessionName : "customer-session" ,
582+ SessionPolicyArn : testSessionPolicyArn ,
583+ }
584+
585+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
586+
587+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
588+
589+ customerRole := assumeRoleArnSessionSequence [0 ]
590+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
591+ Expect (customerRole .Name ).To (Equal (CustomerRoleArnName ))
592+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
593+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (testSessionPolicyArn ))
594+ })
595+
596+ It ("should not set PolicyARNs for non-customer roles" , func () {
597+ roleChainResponse := assumeChainResponse {
598+ AssumptionSequence : []namedRoleArn {
599+ {
600+ Name : "Support-Role-Arn" ,
601+ Arn : "arn:aws:iam::123456789012:role/support-role" ,
602+ },
603+ },
604+ CustomerRoleSessionName : "customer-session" ,
605+ SessionPolicyArn : testSessionPolicyArn ,
606+ }
607+
608+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
609+
610+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
611+
612+ supportRole := assumeRoleArnSessionSequence [0 ]
613+ Expect (supportRole .IsCustomerRole ).To (BeFalse ())
614+ Expect (supportRole .Name ).To (Equal ("Support-Role-Arn" ))
615+ Expect (len (supportRole .PolicyARNs )).To (Equal (0 ))
616+ })
617+
618+ // Generated by Cursor
619+ It ("should handle empty SessionPolicyArn for customer roles" , func () {
620+ roleChainResponse := assumeChainResponse {
621+ AssumptionSequence : []namedRoleArn {
622+ {
623+ Name : CustomerRoleArnName ,
624+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
625+ },
626+ },
627+ CustomerRoleSessionName : "customer-session" ,
628+ SessionPolicyArn : "" , // Empty session policy ARN
629+ }
630+
631+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
632+
633+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
634+
635+ customerRole := assumeRoleArnSessionSequence [0 ]
636+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
637+ Expect (customerRole .Name ).To (Equal (CustomerRoleArnName ))
638+ Expect (len (customerRole .PolicyARNs )).To (Equal (0 ))
639+ })
640+ })
641+
642+ Context ("error scenarios with PolicyARNs" , func () {
643+ It ("should handle invalid SessionPolicyArn gracefully" , func () {
644+ roleChainResponse := assumeChainResponse {
645+ AssumptionSequence : []namedRoleArn {
646+ {
647+ Name : CustomerRoleArnName ,
648+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
649+ },
650+ },
651+ CustomerRoleSessionName : "customer-session" ,
652+ SessionPolicyArn : "invalid-arn-format" , // Invalid ARN format
653+ }
654+
655+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
656+
657+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
658+
659+ customerRole := assumeRoleArnSessionSequence [0 ]
660+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
661+ Expect (customerRole .Name ).To (Equal (CustomerRoleArnName ))
662+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
663+ // The invalid ARN is still passed through - validation happens at AWS level
664+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal ("invalid-arn-format" ))
665+ })
666+
667+ It ("should handle missing AssumptionSequence" , func () {
668+ roleChainResponse := assumeChainResponse {
669+ AssumptionSequence : []namedRoleArn {}, // Empty sequence
670+ CustomerRoleSessionName : "customer-session" ,
671+ SessionPolicyArn : testSessionPolicyArn ,
672+ }
673+
674+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
675+
676+ // Should result in empty sequence
677+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (0 ))
678+ })
679+
680+ It ("should handle malformed role ARNs in AssumptionSequence" , func () {
681+ roleChainResponse := assumeChainResponse {
682+ AssumptionSequence : []namedRoleArn {
683+ {
684+ Name : CustomerRoleArnName ,
685+ Arn : "malformed-role-arn" , // Invalid role ARN format
686+ },
687+ },
688+ CustomerRoleSessionName : "customer-session" ,
689+ SessionPolicyArn : testSessionPolicyArn ,
690+ }
691+
692+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
693+
694+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
695+
696+ customerRole := assumeRoleArnSessionSequence [0 ]
697+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
698+ Expect (customerRole .RoleArn ).To (Equal ("malformed-role-arn" )) // Malformed ARN is passed through
699+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
700+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (testSessionPolicyArn ))
701+ })
702+
703+ It ("should handle extremely long SessionPolicyArn" , func () {
704+ // Create a very long policy ARN that might cause issues
705+ longPolicyArn := "arn:aws:iam::123456789012:policy/" + strings .Repeat ("a" , 500 )
706+
707+ roleChainResponse := assumeChainResponse {
708+ AssumptionSequence : []namedRoleArn {
709+ {
710+ Name : CustomerRoleArnName ,
711+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
712+ },
713+ },
714+ CustomerRoleSessionName : "customer-session" ,
715+ SessionPolicyArn : longPolicyArn ,
716+ }
717+
718+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
719+
720+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
721+
722+ customerRole := assumeRoleArnSessionSequence [0 ]
723+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
724+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
725+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (longPolicyArn ))
726+ // Verify the ARN length
727+ Expect (len (* customerRole .PolicyARNs [0 ].Arn )).To (BeNumerically (">" , 500 ))
728+ })
729+
730+ It ("should handle special characters in SessionPolicyArn" , func () {
731+ // Policy ARN with special characters (though this would be invalid in real AWS)
732+ specialCharsArn := "arn:aws:iam::123456789012:policy/test-policy-with-special-chars!@#$%"
733+
734+ roleChainResponse := assumeChainResponse {
735+ AssumptionSequence : []namedRoleArn {
736+ {
737+ Name : CustomerRoleArnName ,
738+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
739+ },
740+ },
741+ CustomerRoleSessionName : "customer-session" ,
742+ SessionPolicyArn : specialCharsArn ,
743+ }
744+
745+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
746+
747+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
748+
749+ customerRole := assumeRoleArnSessionSequence [0 ]
750+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
751+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
752+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (specialCharsArn ))
753+ })
754+
755+ It ("should verify debug logging when SessionPolicyArn is non-empty" , func () {
756+ roleChainResponse := assumeChainResponse {
757+ AssumptionSequence : []namedRoleArn {
758+ {
759+ Name : CustomerRoleArnName ,
760+ Arn : "arn:aws:iam::123456789012:role/customer-role" ,
761+ },
762+ },
763+ CustomerRoleSessionName : "customer-session" ,
764+ SessionPolicyArn : testSessionPolicyArn , // Non-empty SessionPolicyArn
765+ }
766+
767+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
768+
769+ // Verify the non-empty SessionPolicyArn scenario
770+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (1 ))
771+
772+ customerRole := assumeRoleArnSessionSequence [0 ]
773+
774+ // Verify the customer role identification
775+ Expect (customerRole .IsCustomerRole ).To (BeTrue ())
776+ Expect (customerRole .Name ).To (Equal (CustomerRoleArnName ))
777+ Expect (customerRole .RoleSessionName ).To (Equal ("customer-session" ))
778+
779+ // Verify that SessionPolicyArn is non-empty
780+ Expect (roleChainResponse .SessionPolicyArn ).ToNot (BeEmpty ())
781+
782+ // Verify PolicyARNs array is populated correctly
783+ Expect (len (customerRole .PolicyARNs )).To (Equal (1 ))
784+ Expect (customerRole .PolicyARNs [0 ].Arn ).ToNot (BeNil ())
785+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (testSessionPolicyArn ))
786+
787+ // Verify the exact SessionPolicyArn value matches
788+ Expect (* customerRole .PolicyARNs [0 ].Arn ).To (Equal (roleChainResponse .SessionPolicyArn ))
789+ })
790+
791+ It ("should handle multiple customer roles with same SessionPolicyArn" , func () {
792+ // Test scenario with multiple customer roles getting the same session policy
793+ roleChainResponse := assumeChainResponse {
794+ AssumptionSequence : []namedRoleArn {
795+ {
796+ Name : CustomerRoleArnName ,
797+ Arn : "arn:aws:iam::123456789012:role/customer-role-1" ,
798+ },
799+ {
800+ Name : "Support-Role-Arn" ,
801+ Arn : "arn:aws:iam::123456789012:role/support-role" ,
802+ },
803+ {
804+ Name : CustomerRoleArnName , // Another customer role
805+ Arn : "arn:aws:iam::123456789012:role/customer-role-2" ,
806+ },
807+ },
808+ CustomerRoleSessionName : "customer-session" ,
809+ SessionPolicyArn : testSessionPolicyArn ,
810+ }
811+
812+ assumeRoleArnSessionSequence := simulateGetIsolatedCredentialsLogic (roleChainResponse )
813+
814+ Expect (len (assumeRoleArnSessionSequence )).To (Equal (3 ))
815+
816+ // Verify first customer role
817+ customerRole1 := assumeRoleArnSessionSequence [0 ]
818+ Expect (customerRole1 .IsCustomerRole ).To (BeTrue ())
819+ Expect (customerRole1 .Name ).To (Equal (CustomerRoleArnName ))
820+ Expect (len (customerRole1 .PolicyARNs )).To (Equal (1 ))
821+ Expect (* customerRole1 .PolicyARNs [0 ].Arn ).To (Equal (testSessionPolicyArn ))
822+
823+ // Verify support role (non-customer)
824+ supportRole := assumeRoleArnSessionSequence [1 ]
825+ Expect (supportRole .IsCustomerRole ).To (BeFalse ())
826+ Expect (supportRole .Name ).To (Equal ("Support-Role-Arn" ))
827+ Expect (len (supportRole .PolicyARNs )).To (Equal (0 ))
828+
829+ // Verify second customer role
830+ customerRole2 := assumeRoleArnSessionSequence [2 ]
831+ Expect (customerRole2 .IsCustomerRole ).To (BeTrue ())
832+ Expect (customerRole2 .Name ).To (Equal (CustomerRoleArnName ))
833+ Expect (len (customerRole2 .PolicyARNs )).To (Equal (1 ))
834+ Expect (* customerRole2 .PolicyARNs [0 ].Arn ).To (Equal (testSessionPolicyArn ))
835+ })
836+ })
837+ })
0 commit comments