1
1
import { AssumeRoleCommand , STSClient } from "@aws-sdk/nested-clients/sts" ;
2
- import { beforeEach , describe , expect , test as it , vi } from "vitest" ;
2
+ import { LoadedConfigSelectors } from "@smithy/node-config-provider" ;
3
+ import type { ParsedIniData } from "@smithy/types" ;
4
+ import { afterEach , beforeEach , describe , expect , test as it , vi } from "vitest" ;
3
5
4
6
import { fromTemporaryCredentials as fromTemporaryCredentialsNode } from "./fromTemporaryCredentials" ;
5
7
import { fromTemporaryCredentials } from "./fromTemporaryCredentials.base" ;
6
8
7
9
const mockSend = vi . fn ( ) ;
8
10
const mockUsePlugin = vi . fn ( ) ;
11
+
9
12
vi . mock ( "@aws-sdk/nested-clients/sts" , ( ) => ( {
10
13
STSClient : vi . fn ( ) . mockImplementation ( ( config ) => ( {
11
14
config,
12
15
send : vi . fn ( ) . mockImplementation ( async function ( command ) {
13
16
// Mock resolving client credentials provider at send()
14
- if ( typeof config . credentials === "function" ) config . credentials = await config . credentials ( ) ;
15
- return await mockSend ( command ) ;
17
+ if ( typeof config . credentials === "function" ) {
18
+ config . credentials = await config . credentials ( ) ;
19
+ }
20
+ return mockSend ( command ) ;
16
21
} ) ,
17
22
middlewareStack : { use : mockUsePlugin } ,
18
23
} ) ) ,
@@ -25,6 +30,20 @@ vi.mock("@aws-sdk/nested-clients/sts", () => ({
25
30
} ) ,
26
31
} ) ) ;
27
32
33
+ let iniProfileData : ParsedIniData = null as any ;
34
+ vi . mock ( import ( "@smithy/node-config-provider" ) , async ( importOriginal ) => {
35
+ return {
36
+ ...( await importOriginal ( ) ) ,
37
+ loadConfig : ( (
38
+ { environmentVariableSelector, configFileSelector, default : defaultValue } : LoadedConfigSelectors < any > ,
39
+ { profile = process . env . AWS_PROFILE ?? "default" } : { profile ?: string }
40
+ ) => {
41
+ return ( ) =>
42
+ environmentVariableSelector ( process . env ) ?? configFileSelector ( iniProfileData [ profile ] ?? { } ) ?? defaultValue ( ) ;
43
+ } ) as any ,
44
+ } ;
45
+ } ) ;
46
+
28
47
describe ( "fromTemporaryCredentials" , ( ) => {
29
48
const RoleArn = "ROLE_ARN" ;
30
49
const RoleSessionName = "ROLE_SESSION_NAME" ;
@@ -33,16 +52,32 @@ describe("fromTemporaryCredentials", () => {
33
52
secretAccessKey : "SECRET_ACCESS_KEY" ,
34
53
} ;
35
54
const region = "US_BAR_1" ;
55
+ let processSnapshot : Record < string , any > ;
36
56
37
57
beforeEach ( ( ) => {
38
58
vi . clearAllMocks ( ) ;
39
- mockSend . mockResolvedValueOnce ( {
59
+ mockSend . mockResolvedValue ( {
40
60
Credentials : {
41
61
AccessKeyId : "ACCESS_KEY_ID" ,
42
62
SecretAccessKey : "SECRET_ACCESS_KEY" ,
43
63
SessionToken : "SESSION_TOKEN" ,
44
64
} ,
45
65
} ) ;
66
+
67
+ processSnapshot = {
68
+ ...process . env ,
69
+ } ;
70
+ process . env = { } ;
71
+
72
+ iniProfileData = {
73
+ default : {
74
+ region : "us-west-2" ,
75
+ } ,
76
+ } ;
77
+ } ) ;
78
+
79
+ afterEach ( ( ) => {
80
+ process . env = processSnapshot ;
46
81
} ) ;
47
82
48
83
it ( "should call STS::AssumeRole API with master credentials" , async ( ) => {
@@ -91,7 +126,7 @@ describe("fromTemporaryCredentials", () => {
91
126
credentials : masterCredentials ,
92
127
logger : void 0 ,
93
128
profile : void 0 ,
94
- region : "us-east-1" ,
129
+ region : "us-west-2" , // profile default
95
130
requestHandler : void 0 ,
96
131
} ) ;
97
132
expect ( mockUsePlugin ) . toHaveBeenCalledTimes ( 1 ) ;
@@ -101,6 +136,7 @@ describe("fromTemporaryCredentials", () => {
101
136
it ( "should create a role session name if none provided" , async ( ) => {
102
137
const provider = fromTemporaryCredentialsNode ( {
103
138
params : { RoleArn } ,
139
+ masterCredentials,
104
140
} ) ;
105
141
await provider ( ) ;
106
142
expect ( AssumeRoleCommand as unknown as any ) . toHaveBeenCalledWith ( {
@@ -299,6 +335,7 @@ describe("fromTemporaryCredentials", () => {
299
335
const provider = fromTemporaryCredentialsNode ( {
300
336
params : { RoleArn, SerialNumber, RoleSessionName } ,
301
337
mfaCodeProvider,
338
+ masterCredentials,
302
339
} ) ;
303
340
await provider ( ) ;
304
341
expect ( mfaCodeProvider ) . toHaveBeenCalledWith ( SerialNumber ) ;
@@ -326,4 +363,121 @@ describe("fromTemporaryCredentials", () => {
326
363
expect ( e . tryNextLink ) . toBe ( false ) ;
327
364
}
328
365
} ) ;
366
+
367
+ describe ( "env configuration" , ( ) => {
368
+ beforeEach ( ( ) => {
369
+ iniProfileData = {
370
+ default : {
371
+ region : "us-west-2" ,
372
+ } ,
373
+ abc : {
374
+ region : "eu-central-1" ,
375
+ } ,
376
+ xyz : {
377
+ region : "us-west-1" ,
378
+ } ,
379
+ regionless : { } ,
380
+ } ;
381
+ } ) ;
382
+
383
+ it ( "should allow region configuration from config file" , async ( ) => {
384
+ const provider = fromTemporaryCredentialsNode ( {
385
+ params : {
386
+ RoleArn,
387
+ RoleSessionName,
388
+ } ,
389
+ masterCredentials,
390
+ } ) ;
391
+ await provider ( ) ;
392
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
393
+ region : "us-west-2" ,
394
+ } ) ;
395
+ } ) ;
396
+
397
+ it ( "should allow region configuration from config file non-default profile" , async ( ) => {
398
+ // SDK does not use AWS_DEFAULT_PROFILE.
399
+ process . env . AWS_PROFILE = "xyz" ;
400
+ const provider = fromTemporaryCredentialsNode ( {
401
+ params : {
402
+ RoleArn,
403
+ RoleSessionName,
404
+ } ,
405
+ masterCredentials,
406
+ } ) ;
407
+ await provider ( ) ;
408
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
409
+ region : "us-west-1" ,
410
+ } ) ;
411
+ } ) ;
412
+
413
+ it ( "should allow region configuration from env" , async ( ) => {
414
+ // SDK does not use AWS_DEFAULT_REGION.
415
+ process . env . AWS_REGION = "ap-southeast-7" ;
416
+ const provider = fromTemporaryCredentialsNode ( {
417
+ params : {
418
+ RoleArn,
419
+ RoleSessionName,
420
+ } ,
421
+ masterCredentials,
422
+ } ) ;
423
+ await provider ( ) ;
424
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
425
+ region : "ap-southeast-7" ,
426
+ } ) ;
427
+ } ) ;
428
+
429
+ it ( "should allow region configuration from env overriding region in profile" , async ( ) => {
430
+ process . env . AWS_PROFILE = "xyz" ;
431
+ process . env . AWS_REGION = "eu-west-1" ;
432
+ const provider = fromTemporaryCredentialsNode ( {
433
+ params : {
434
+ RoleArn,
435
+ RoleSessionName,
436
+ } ,
437
+ masterCredentials,
438
+ } ) ;
439
+ await provider ( ) ;
440
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
441
+ region : "eu-west-1" ,
442
+ } ) ;
443
+ } ) ;
444
+
445
+ it ( "should allow region configuration from env overriding region in profile where profile in code overrides env profile" , async ( ) => {
446
+ process . env . AWS_PROFILE = "xyz" ;
447
+ const provider = fromTemporaryCredentialsNode ( {
448
+ params : {
449
+ RoleArn,
450
+ RoleSessionName,
451
+ } ,
452
+ masterCredentials,
453
+ clientConfig : {
454
+ profile : "abc" ,
455
+ } ,
456
+ } ) ;
457
+ await provider ( ) ;
458
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
459
+ region : "eu-central-1" ,
460
+ } ) ;
461
+ } ) ;
462
+
463
+ it ( "should use us-east-1 if no region is configured anywhere" , async ( ) => {
464
+ // no configured region for the provider
465
+ // no caller client with region
466
+ // no region env
467
+ // no region in profile
468
+ process . env . AWS_PROFILE = "regionless" ;
469
+ process . env . AWS_REGION = undefined ;
470
+ const provider = fromTemporaryCredentialsNode ( {
471
+ params : {
472
+ RoleArn,
473
+ RoleSessionName,
474
+ } ,
475
+ masterCredentials,
476
+ } ) ;
477
+ await provider ( ) ;
478
+ expect ( vi . mocked ( STSClient as any ) . mock . calls [ 0 ] [ 0 ] ) . toMatchObject ( {
479
+ region : "us-east-1" ,
480
+ } ) ;
481
+ } ) ;
482
+ } ) ;
329
483
} ) ;
0 commit comments