@@ -4,32 +4,39 @@ import type {
4
4
CredentialProviderOptions ,
5
5
RuntimeConfigAwsCredentialIdentityProvider ,
6
6
} from "@aws-sdk/types" ;
7
+ import { normalizeProvider } from "@smithy/core" ;
7
8
import { CredentialsProviderError } from "@smithy/property-provider" ;
8
- import { AwsCredentialIdentity , AwsCredentialIdentityProvider , Pluggable } from "@smithy/types" ;
9
+ import { AwsCredentialIdentity , AwsCredentialIdentityProvider , Logger , Pluggable , RequestHandler } from "@smithy/types" ;
9
10
10
11
export interface FromTemporaryCredentialsOptions extends CredentialProviderOptions {
11
12
params : Omit < AssumeRoleCommandInput , "RoleSessionName" > & { RoleSessionName ?: string } ;
12
13
masterCredentials ?: AwsCredentialIdentity | AwsCredentialIdentityProvider ;
13
14
clientConfig ?: STSClientConfig ;
15
+ logger ?: Logger ;
14
16
clientPlugins ?: Pluggable < any , any > [ ] ;
15
17
mfaCodeProvider ?: ( mfaSerial : string ) => Promise < string > ;
16
18
}
17
19
20
+ const ASSUME_ROLE_DEFAULT_REGION = "us-east-1" ;
21
+
18
22
export const fromTemporaryCredentials = (
19
23
options : FromTemporaryCredentialsOptions ,
20
24
credentialDefaultProvider ?: ( ) => AwsCredentialIdentityProvider
21
25
) : RuntimeConfigAwsCredentialIdentityProvider => {
22
26
let stsClient : STSClient ;
23
27
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
+
25
32
const params = { ...options . params , RoleSessionName : options . params . RoleSessionName ?? "aws-sdk-js-" + Date . now ( ) } ;
26
33
if ( params ?. SerialNumber ) {
27
34
if ( ! options . mfaCodeProvider ) {
28
35
throw new CredentialsProviderError (
29
36
`Temporary credential requires multi-factor authentication, but no MFA code callback was provided.` ,
30
37
{
31
38
tryNextLink : false ,
32
- logger : options . logger ,
39
+ logger,
33
40
}
34
41
) ;
35
42
}
@@ -42,14 +49,68 @@ export const fromTemporaryCredentials = (
42
49
const defaultCredentialsOrError =
43
50
typeof credentialDefaultProvider === "function" ? credentialDefaultProvider ( ) : undefined ;
44
51
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
+
46
107
stsClient = new STSClient ( {
47
108
...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 ) ,
53
114
} ) ;
54
115
}
55
116
if ( options . clientPlugins ) {
@@ -60,7 +121,7 @@ export const fromTemporaryCredentials = (
60
121
const { Credentials } = await stsClient . send ( new AssumeRoleCommand ( params ) ) ;
61
122
if ( ! Credentials || ! Credentials . AccessKeyId || ! Credentials . SecretAccessKey ) {
62
123
throw new CredentialsProviderError ( `Invalid response from STS.assumeRole call with role ${ params . RoleArn } ` , {
63
- logger : options . logger ,
124
+ logger,
64
125
} ) ;
65
126
}
66
127
return {
@@ -73,3 +134,21 @@ export const fromTemporaryCredentials = (
73
134
} ;
74
135
} ;
75
136
} ;
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