From 7c1771719f2f6e2907bae9097b437ab1efece8aa Mon Sep 17 00:00:00 2001 From: George Fu Date: Thu, 23 Oct 2025 13:09:57 -0400 Subject: [PATCH] fix(credential-provider-web-identity): make fromTokenFile aware of runtime caller client --- .../credential-provider-node.integ.spec.ts | 53 ++++++++++++++++++- .../src/fromTokenFile.ts | 10 ++-- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/packages/credential-provider-node/tests/credential-provider-node.integ.spec.ts b/packages/credential-provider-node/tests/credential-provider-node.integ.spec.ts index e2bc97d60978..b9a9412097bb 100644 --- a/packages/credential-provider-node/tests/credential-provider-node.integ.spec.ts +++ b/packages/credential-provider-node/tests/credential-provider-node.integ.spec.ts @@ -3,7 +3,13 @@ import { externalDataInterceptor } from "@smithy/shared-ini-file-loader"; import { NodeHttpHandler } from "@smithy/node-http-handler"; import { STS, STSExtensionConfiguration } from "@aws-sdk/client-sts"; import * as credentialProviderHttp from "@aws-sdk/credential-provider-http"; -import { fromCognitoIdentity, fromCognitoIdentityPool, fromIni, fromWebToken } from "@aws-sdk/credential-providers"; +import { + fromCognitoIdentity, + fromCognitoIdentityPool, + fromIni, + fromWebToken, + fromTokenFile, +} from "@aws-sdk/credential-providers"; import { HttpResponse } from "@smithy/protocol-http"; import type { HttpRequest, MiddlewareStack, NodeHttpHandlerOptions, ParsedIniData } from "@smithy/types"; import { AdaptiveRetryStrategy, StandardRetryStrategy } from "@smithy/util-retry"; @@ -777,6 +783,51 @@ describe("credential-provider-node integration test", () => { }); describe("fromTokenFile", () => { + it("should use the caller client region when combined with one", async () => { + sts = new STS({ + region: "ap-northeast-1", + credentials: fromTokenFile({ + roleArn: "ROLE_ARN", + webIdentityTokenFile: "token-filepath", + }), + }); + await sts.getCallerIdentity({}); + const credentials = await sts.config.credentials(); + expect(credentials).toEqual({ + accessKeyId: "STS_ARWI_ACCESS_KEY_ID", + secretAccessKey: "STS_ARWI_SECRET_ACCESS_KEY", + sessionToken: "STS_ARWI_SESSION_TOKEN_ap-northeast-1", + expiration: new Date("3000-01-01T00:00:00.000Z"), + $source: { + CREDENTIALS_CODE: "e", + CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: "k", + }, + }); + }); + + it("should use the caller client region if derived from AWS_REGION", async () => { + process.env.AWS_REGION = "eu-west-2"; + const provider = fromTokenFile({ + roleArn: "ROLE_ARN", + webIdentityTokenFile: "token-filepath", + }); + sts = new STS({ + credentials: provider, + }); + await sts.getCallerIdentity({}); + const credentials = await sts.config.credentials(); + expect(credentials).toEqual({ + accessKeyId: "STS_ARWI_ACCESS_KEY_ID", + secretAccessKey: "STS_ARWI_SECRET_ACCESS_KEY", + sessionToken: "STS_ARWI_SESSION_TOKEN_eu-west-2", + expiration: new Date("3000-01-01T00:00:00.000Z"), + $source: { + CREDENTIALS_CODE: "e", + CREDENTIALS_STS_ASSUME_ROLE_WEB_ID: "k", + }, + }); + }); + it("should resolve credentials with STS assumeRoleWithWebIdentity using a token", async () => { process.env.AWS_WEB_IDENTITY_TOKEN_FILE = "token-filepath"; process.env.AWS_ROLE_ARN = "ROLE_ARN"; diff --git a/packages/credential-provider-web-identity/src/fromTokenFile.ts b/packages/credential-provider-web-identity/src/fromTokenFile.ts index 88cf9a674c68..e64f61e7213a 100644 --- a/packages/credential-provider-web-identity/src/fromTokenFile.ts +++ b/packages/credential-provider-web-identity/src/fromTokenFile.ts @@ -1,8 +1,8 @@ import { setCredentialFeature } from "@aws-sdk/core/client"; -import { AttributedAwsCredentialIdentity, CredentialProviderOptions } from "@aws-sdk/types"; +import type { AttributedAwsCredentialIdentity, CredentialProviderOptions } from "@aws-sdk/types"; +import { AwsIdentityProperties, RuntimeConfigAwsCredentialIdentityProvider } from "@aws-sdk/types/src"; import { CredentialsProviderError } from "@smithy/property-provider"; import { externalDataInterceptor } from "@smithy/shared-ini-file-loader"; -import type { AwsCredentialIdentityProvider } from "@smithy/types"; import { readFileSync } from "fs"; import { fromWebToken, FromWebTokenInit } from "./fromWebToken"; @@ -29,8 +29,8 @@ export interface FromTokenFileInit * Represents OIDC credentials from a file on disk. */ export const fromTokenFile = - (init: FromTokenFileInit = {}): AwsCredentialIdentityProvider => - async () => { + (init: FromTokenFileInit = {}): RuntimeConfigAwsCredentialIdentityProvider => + async (awsIdentityProperties?: AwsIdentityProperties) => { init.logger?.debug("@aws-sdk/credential-provider-web-identity - fromTokenFile"); const webIdentityTokenFile = init?.webIdentityTokenFile ?? process.env[ENV_TOKEN_FILE]; const roleArn = init?.roleArn ?? process.env[ENV_ROLE_ARN]; @@ -49,7 +49,7 @@ export const fromTokenFile = readFileSync(webIdentityTokenFile, { encoding: "ascii" }), roleArn, roleSessionName, - })(); + })(awsIdentityProperties); if (webIdentityTokenFile === process.env[ENV_TOKEN_FILE]) { setCredentialFeature(credentials, "CREDENTIALS_ENV_VARS_STS_WEB_ID_TOKEN", "h");