@@ -4,32 +4,39 @@ import type {
44 CredentialProviderOptions ,
55 RuntimeConfigAwsCredentialIdentityProvider ,
66} from "@aws-sdk/types" ;
7+ import { normalizeProvider } from "@smithy/core" ;
78import { CredentialsProviderError } from "@smithy/property-provider" ;
8- import { AwsCredentialIdentity , AwsCredentialIdentityProvider , Pluggable } from "@smithy/types" ;
9+ import { AwsCredentialIdentity , AwsCredentialIdentityProvider , Logger , Pluggable , RequestHandler } from "@smithy/types" ;
910
1011export interface FromTemporaryCredentialsOptions extends CredentialProviderOptions {
1112 params : Omit < AssumeRoleCommandInput , "RoleSessionName" > & { RoleSessionName ?: string } ;
1213 masterCredentials ?: AwsCredentialIdentity | AwsCredentialIdentityProvider ;
1314 clientConfig ?: STSClientConfig ;
15+ logger ?: Logger ;
1416 clientPlugins ?: Pluggable < any , any > [ ] ;
1517 mfaCodeProvider ?: ( mfaSerial : string ) => Promise < string > ;
1618}
1719
20+ const ASSUME_ROLE_DEFAULT_REGION = "us-east-1" ;
21+
1822export const fromTemporaryCredentials = (
1923 options : FromTemporaryCredentialsOptions ,
2024 credentialDefaultProvider ?: ( ) => AwsCredentialIdentityProvider
2125) : RuntimeConfigAwsCredentialIdentityProvider => {
2226 let stsClient : STSClient ;
2327 return async ( awsIdentityProperties : AwsIdentityProperties = { } ) : Promise < AwsCredentialIdentity > => {
24- options . logger ?. debug ( "@aws-sdk/credential-providers - fromTemporaryCredentials (STS)" ) ;
28+ const { callerClientConfig } = awsIdentityProperties ;
29+ const logger = options . logger ?? callerClientConfig ?. logger ;
30+ logger ?. debug ( "@aws-sdk/credential-providers - fromTemporaryCredentials (STS)" ) ;
31+
2532 const params = { ...options . params , RoleSessionName : options . params . RoleSessionName ?? "aws-sdk-js-" + Date . now ( ) } ;
2633 if ( params ?. SerialNumber ) {
2734 if ( ! options . mfaCodeProvider ) {
2835 throw new CredentialsProviderError (
2936 `Temporary credential requires multi-factor authentication, but no MFA code callback was provided.` ,
3037 {
3138 tryNextLink : false ,
32- logger : options . logger ,
39+ logger,
3340 }
3441 ) ;
3542 }
@@ -42,14 +49,68 @@ export const fromTemporaryCredentials = (
4249 const defaultCredentialsOrError =
4350 typeof credentialDefaultProvider === "function" ? credentialDefaultProvider ( ) : undefined ;
4451
45- const { callerClientConfig } = awsIdentityProperties ;
52+ const credentialSources = [
53+ options . masterCredentials ,
54+ options . clientConfig ?. credentials ,
55+ /**
56+ * Important (!): callerClientConfig?.credentials is not a valid
57+ * credential source for this provider, because this function
58+ * is the caller client's credential provider function.
59+ */
60+ void callerClientConfig ?. credentials ,
61+ callerClientConfig ?. credentialDefaultProvider ?.( ) ,
62+ defaultCredentialsOrError ,
63+ ] ;
64+ let credentialSource = "STS client default credentials" ;
65+ if ( credentialSources [ 0 ] ) {
66+ credentialSource = "options.masterCredentials" ;
67+ } else if ( credentialSources [ 1 ] ) {
68+ credentialSource = "options.clientConfig.credentials" ;
69+ } else if ( credentialSources [ 2 ] ) {
70+ // This branch is not possible, see above void note.
71+ // This code is here to prevent accidental attempts to utilize
72+ // the invalid credential source.
73+ credentialSource = "caller client's credentials" ;
74+ throw new Error ( "fromTemporaryCredentials recursion in callerClientConfig.credentials" ) ;
75+ } else if ( credentialSources [ 3 ] ) {
76+ credentialSource = "caller client's credentialDefaultProvider" ;
77+ } else if ( credentialSources [ 4 ] ) {
78+ credentialSource = "AWS SDK default credentials" ;
79+ }
80+
81+ const regionSources = [ options . clientConfig ?. region , callerClientConfig ?. region , ASSUME_ROLE_DEFAULT_REGION ] ;
82+ let regionSource = "default partition's default region" ;
83+ if ( regionSources [ 0 ] ) {
84+ regionSource = "options.clientConfig.region" ;
85+ } else if ( regionSources [ 1 ] ) {
86+ regionSource = "caller client's region" ;
87+ }
88+
89+ const requestHandlerSources = [
90+ filterRequestHandler ( options . clientConfig ?. requestHandler ) ,
91+ filterRequestHandler ( callerClientConfig ?. requestHandler ) ,
92+ ] ;
93+ let requestHandlerSource = "STS default requestHandler" ;
94+ if ( requestHandlerSources [ 0 ] ) {
95+ requestHandlerSource = "options.clientConfig.requestHandler" ;
96+ } else if ( requestHandlerSources [ 1 ] ) {
97+ requestHandlerSource = "caller client's requestHandler" ;
98+ }
99+
100+ logger ?. debug ?.(
101+ `@aws-sdk/credential-providers - fromTemporaryCredentials STS client init with ` +
102+ `${ regionSource } =${ await normalizeProvider (
103+ coalesce ( regionSources )
104+ ) ( ) } , ${ credentialSource } , ${ requestHandlerSource } .`
105+ ) ;
106+
46107 stsClient = new STSClient ( {
47108 ...options . clientConfig ,
48- credentials :
49- options . masterCredentials ??
50- options . clientConfig ?. credentials ??
51- callerClientConfig ?. credentialDefaultProvider ?. ( ) ??
52- defaultCredentialsOrError ,
109+ credentials : coalesce ( credentialSources ) ,
110+ logger ,
111+ profile : options . clientConfig ?. profile ?? callerClientConfig ?. profile ,
112+ region : coalesce ( regionSources ) ,
113+ requestHandler : coalesce ( requestHandlerSources ) ,
53114 } ) ;
54115 }
55116 if ( options . clientPlugins ) {
@@ -60,7 +121,7 @@ export const fromTemporaryCredentials = (
60121 const { Credentials } = await stsClient . send ( new AssumeRoleCommand ( params ) ) ;
61122 if ( ! Credentials || ! Credentials . AccessKeyId || ! Credentials . SecretAccessKey ) {
62123 throw new CredentialsProviderError ( `Invalid response from STS.assumeRole call with role ${ params . RoleArn } ` , {
63- logger : options . logger ,
124+ logger,
64125 } ) ;
65126 }
66127 return {
@@ -73,3 +134,21 @@ export const fromTemporaryCredentials = (
73134 } ;
74135 } ;
75136} ;
137+
138+ /**
139+ * @internal
140+ */
141+ const filterRequestHandler = ( requestHandler : STSClientConfig [ "requestHandler" ] ) : undefined | typeof requestHandler => {
142+ return ( requestHandler as RequestHandler < any , any > ) ?. metadata ?. handlerProtocol === "h2" ? undefined : requestHandler ;
143+ } ;
144+
145+ /**
146+ * @internal
147+ */
148+ const coalesce = ( args : any ) => {
149+ for ( const item of args ) {
150+ if ( item !== undefined ) {
151+ return item ;
152+ }
153+ }
154+ } ;
0 commit comments