@@ -692,59 +692,88 @@ describe('InstrumentationPatchTest', () => {
692692 } ) ;
693693 } ) ;
694694
695- it ( 'Prevents recursion when credentials provider makes STS calls' , async ( ) => {
696- // Track credentials provider calls and skip flag state
697- let credentialsProviderCallCount = 0 ;
698- let skipCredentialCaptureValue = false ;
699-
700- // Mock span for attribute capture
701- const mockSpan = { setAttribute : sinon . stub ( ) } ;
702- sinon . stub ( trace , 'getSpan' ) . returns ( mockSpan as unknown as Span ) ;
703-
704- // Mock OpenTelemetry context to track skip-credential-capture flag
705- const mockContext = {
706- getValue : ( key : symbol ) =>
707- key . toString ( ) . includes ( 'skip-credential-capture' ) ? skipCredentialCaptureValue : undefined ,
708- setValue : ( key : symbol , value : any ) => {
709- if ( key . toString ( ) . includes ( 'skip-credential-capture' ) ) skipCredentialCaptureValue = value ;
710- return mockContext ;
711- } ,
712- deleteValue : ( ) => mockContext ,
713- } ;
714- sinon . stub ( context , 'active' ) . returns ( mockContext ) ;
715-
716- // Capture middleware added to stack
717- const middlewareStack : any [ ] = [ ] ;
718- const recursiveSdkSend = extractAwsSdkInstrumentation ( PATCHED_INSTRUMENTATIONS )
719- [ '_getV3SmithyClientSendPatch' ] ( ( ) => Promise . resolve ( ) )
720- . bind ( {
721- middlewareStack : { add : ( middleware : any , config : any ) => middlewareStack . push ( [ middleware , config ] ) } ,
722- config : {
723- // Credentials provider that recursively calls SDK (simulates STS)
724- credentials : async ( ) => {
725- credentialsProviderCallCount ++ ;
726- await recursiveSdkSend ( { } , null ) ;
727- return { accessKeyId : 'test-access-key' } ;
728- } ,
729- region : ( ) => Promise . resolve ( 'us-west-2' ) ,
695+ describe ( 'credential extraction failure handling' , ( ) => {
696+ let credentialsProviderCallCount : number ;
697+ let mockSpan : any ;
698+ let middlewareStack : any [ ] ;
699+ let recursiveSdkSend : any ;
700+ let createSdkSend : ( recursive ?: boolean ) => any ;
701+
702+ beforeEach ( ( ) => {
703+ credentialsProviderCallCount = 0 ;
704+ mockSpan = { setAttribute : sinon . stub ( ) } ;
705+ sinon . stub ( trace , 'getSpan' ) . returns ( mockSpan as unknown as Span ) ;
706+ middlewareStack = [ ] ;
707+
708+ createSdkSend = ( ) => {
709+ return extractAwsSdkInstrumentation ( PATCHED_INSTRUMENTATIONS )
710+ [ '_getV3SmithyClientSendPatch' ] ( ( ) => Promise . resolve ( ) )
711+ . bind ( {
712+ middlewareStack : { add : ( middleware : any , config : any ) => middlewareStack . push ( [ middleware , config ] ) } ,
713+ config : {
714+ credentials : async ( ) => {
715+ credentialsProviderCallCount ++ ;
716+ await recursiveSdkSend ( { } , null ) ;
717+ return { accessKeyId : 'test-access-key' } ;
718+ } ,
719+ region : ( ) => Promise . resolve ( 'us-west-2' ) ,
720+ } ,
721+ } ) ;
722+ } ;
723+ } ) ;
724+
725+ afterEach ( ( ) => {
726+ sinon . restore ( ) ;
727+ } ) ;
728+
729+ it ( 'Prevents recursion when credentials provider makes STS calls' , async ( ) => {
730+ let skipCredentialCaptureValue = false ;
731+ const mockContext = {
732+ getValue : ( key : symbol ) =>
733+ key . toString ( ) . includes ( 'skip-credential-capture' ) ? skipCredentialCaptureValue : undefined ,
734+ setValue : ( key : symbol , value : any ) => {
735+ if ( key . toString ( ) . includes ( 'skip-credential-capture' ) ) skipCredentialCaptureValue = value ;
736+ return mockContext ;
730737 } ,
731- } ) ;
738+ deleteValue : ( ) => mockContext ,
739+ } ;
740+ sinon . stub ( context , 'active' ) . returns ( mockContext ) ;
741+ recursiveSdkSend = createSdkSend ( ) ;
732742
733- // Initial SDK call triggers middleware setup
734- await recursiveSdkSend ( { } , null ) ;
735- expect ( skipCredentialCaptureValue ) . toBe ( false ) ;
743+ await recursiveSdkSend ( { } , null ) ;
744+ await middlewareStack [ 1 ] [ 0 ] ( ( ) => Promise . resolve ( ) , null ) ( { } ) ;
736745
737- // Execute credentials extraction middleware
738- await middlewareStack [ 1 ] [ 0 ] ( ( ) => Promise . resolve ( ) , null ) ( { } ) ;
746+ expect ( credentialsProviderCallCount ) . toBe ( 1 ) ;
747+ expect ( skipCredentialCaptureValue ) . toBe ( true ) ;
748+ expect (
749+ mockSpan . setAttribute . calledWith ( AWS_ATTRIBUTE_KEYS . AWS_AUTH_ACCOUNT_ACCESS_KEY , 'test-access-key' )
750+ ) . toBeTruthy ( ) ;
751+ } ) ;
752+
753+ it ( 'Handles undefined active context gracefully' , async ( ) => {
754+ sinon . stub ( context , 'active' ) . returns ( undefined as any ) ;
755+ recursiveSdkSend = createSdkSend ( ) ;
739756
740- // Verify recursion prevention: only one credentials call despite recursive setup
741- expect ( credentialsProviderCallCount ) . toBe ( 1 ) ;
742- expect ( skipCredentialCaptureValue ) . toBe ( true ) ;
743- expect (
744- mockSpan . setAttribute . calledWith ( AWS_ATTRIBUTE_KEYS . AWS_AUTH_ACCOUNT_ACCESS_KEY , 'test-access-key' )
745- ) . toBeTruthy ( ) ;
757+ await recursiveSdkSend ( { } , null ) ;
758+ await middlewareStack [ 1 ] [ 0 ] ( ( ) => Promise . resolve ( ) , null ) ( { } ) ;
759+ expect ( credentialsProviderCallCount ) . toBe ( 0 ) ;
760+ } ) ;
746761
747- sinon . restore ( ) ;
762+ it ( 'Handles setValue failure gracefully' , async ( ) => {
763+ const mockContext = {
764+ getValue : ( ) => false ,
765+ setValue : ( ) => {
766+ throw new Error ( 'setValue failed' ) ;
767+ } ,
768+ deleteValue : ( ) => mockContext ,
769+ } ;
770+ sinon . stub ( context , 'active' ) . returns ( mockContext ) ;
771+ recursiveSdkSend = createSdkSend ( ) ;
772+
773+ await recursiveSdkSend ( { } , null ) ;
774+ await middlewareStack [ 1 ] [ 0 ] ( ( ) => Promise . resolve ( ) , null ) ( { } ) ;
775+ expect ( credentialsProviderCallCount ) . toBe ( 0 ) ;
776+ } ) ;
748777 } ) ;
749778
750779 it ( 'injects trace context header into request via propagator' , async ( ) => {
0 commit comments