11import { 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" ;
35
46import { fromTemporaryCredentials as fromTemporaryCredentialsNode } from "./fromTemporaryCredentials" ;
57import { fromTemporaryCredentials } from "./fromTemporaryCredentials.base" ;
68
79const mockSend = vi . fn ( ) ;
810const mockUsePlugin = vi . fn ( ) ;
11+
912vi . mock ( "@aws-sdk/nested-clients/sts" , ( ) => ( {
1013 STSClient : vi . fn ( ) . mockImplementation ( ( config ) => ( {
1114 config,
1215 send : vi . fn ( ) . mockImplementation ( async function ( command ) {
1316 // 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 ) ;
1621 } ) ,
1722 middlewareStack : { use : mockUsePlugin } ,
1823 } ) ) ,
@@ -25,6 +30,20 @@ vi.mock("@aws-sdk/nested-clients/sts", () => ({
2530 } ) ,
2631} ) ) ;
2732
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+
2847describe ( "fromTemporaryCredentials" , ( ) => {
2948 const RoleArn = "ROLE_ARN" ;
3049 const RoleSessionName = "ROLE_SESSION_NAME" ;
@@ -33,16 +52,32 @@ describe("fromTemporaryCredentials", () => {
3352 secretAccessKey : "SECRET_ACCESS_KEY" ,
3453 } ;
3554 const region = "US_BAR_1" ;
55+ let processSnapshot : Record < string , any > ;
3656
3757 beforeEach ( ( ) => {
3858 vi . clearAllMocks ( ) ;
39- mockSend . mockResolvedValueOnce ( {
59+ mockSend . mockResolvedValue ( {
4060 Credentials : {
4161 AccessKeyId : "ACCESS_KEY_ID" ,
4262 SecretAccessKey : "SECRET_ACCESS_KEY" ,
4363 SessionToken : "SESSION_TOKEN" ,
4464 } ,
4565 } ) ;
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 ;
4681 } ) ;
4782
4883 it ( "should call STS::AssumeRole API with master credentials" , async ( ) => {
@@ -91,7 +126,7 @@ describe("fromTemporaryCredentials", () => {
91126 credentials : masterCredentials ,
92127 logger : void 0 ,
93128 profile : void 0 ,
94- region : "us-east-1" ,
129+ region : "us-west-2" , // profile default
95130 requestHandler : void 0 ,
96131 } ) ;
97132 expect ( mockUsePlugin ) . toHaveBeenCalledTimes ( 1 ) ;
@@ -101,6 +136,7 @@ describe("fromTemporaryCredentials", () => {
101136 it ( "should create a role session name if none provided" , async ( ) => {
102137 const provider = fromTemporaryCredentialsNode ( {
103138 params : { RoleArn } ,
139+ masterCredentials,
104140 } ) ;
105141 await provider ( ) ;
106142 expect ( AssumeRoleCommand as unknown as any ) . toHaveBeenCalledWith ( {
@@ -299,6 +335,7 @@ describe("fromTemporaryCredentials", () => {
299335 const provider = fromTemporaryCredentialsNode ( {
300336 params : { RoleArn, SerialNumber, RoleSessionName } ,
301337 mfaCodeProvider,
338+ masterCredentials,
302339 } ) ;
303340 await provider ( ) ;
304341 expect ( mfaCodeProvider ) . toHaveBeenCalledWith ( SerialNumber ) ;
@@ -326,4 +363,121 @@ describe("fromTemporaryCredentials", () => {
326363 expect ( e . tryNextLink ) . toBe ( false ) ;
327364 }
328365 } ) ;
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+ } ) ;
329483} ) ;
0 commit comments