diff --git a/packages/credential-providers/src/fromTemporaryCredentials.base.ts b/packages/credential-providers/src/fromTemporaryCredentials.base.ts new file mode 100644 index 000000000000..28c92364070d --- /dev/null +++ b/packages/credential-providers/src/fromTemporaryCredentials.base.ts @@ -0,0 +1,75 @@ +import type { AssumeRoleCommandInput, STSClient, STSClientConfig } from "@aws-sdk/nested-clients/sts"; +import type { + AwsIdentityProperties, + CredentialProviderOptions, + RuntimeConfigAwsCredentialIdentityProvider, +} from "@aws-sdk/types"; +import { CredentialsProviderError } from "@smithy/property-provider"; +import { AwsCredentialIdentity, AwsCredentialIdentityProvider, Pluggable } from "@smithy/types"; + +export interface FromTemporaryCredentialsOptions extends CredentialProviderOptions { + params: Omit & { RoleSessionName?: string }; + masterCredentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider; + clientConfig?: STSClientConfig; + clientPlugins?: Pluggable[]; + mfaCodeProvider?: (mfaSerial: string) => Promise; +} + +export const fromTemporaryCredentials = ( + options: FromTemporaryCredentialsOptions, + credentialDefaultProvider?: () => AwsCredentialIdentityProvider +): RuntimeConfigAwsCredentialIdentityProvider => { + let stsClient: STSClient; + return async (awsIdentityProperties: AwsIdentityProperties = {}): Promise => { + options.logger?.debug("@aws-sdk/credential-providers - fromTemporaryCredentials (STS)"); + const params = { ...options.params, RoleSessionName: options.params.RoleSessionName ?? "aws-sdk-js-" + Date.now() }; + if (params?.SerialNumber) { + if (!options.mfaCodeProvider) { + throw new CredentialsProviderError( + `Temporary credential requires multi-factor authentication, but no MFA code callback was provided.`, + { + tryNextLink: false, + logger: options.logger, + } + ); + } + params.TokenCode = await options.mfaCodeProvider(params?.SerialNumber); + } + + const { AssumeRoleCommand, STSClient } = await import("./loadSts"); + + if (!stsClient) { + const defaultCredentialsOrError = + typeof credentialDefaultProvider === "function" ? credentialDefaultProvider() : undefined; + + const { callerClientConfig } = awsIdentityProperties; + stsClient = new STSClient({ + ...options.clientConfig, + credentials: + options.masterCredentials ?? + options.clientConfig?.credentials ?? + callerClientConfig?.credentialDefaultProvider?.() ?? + defaultCredentialsOrError, + }); + } + if (options.clientPlugins) { + for (const plugin of options.clientPlugins) { + stsClient.middlewareStack.use(plugin); + } + } + const { Credentials } = await stsClient.send(new AssumeRoleCommand(params)); + if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) { + throw new CredentialsProviderError(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`, { + logger: options.logger, + }); + } + return { + accessKeyId: Credentials.AccessKeyId, + secretAccessKey: Credentials.SecretAccessKey, + sessionToken: Credentials.SessionToken, + expiration: Credentials.Expiration, + // TODO(credentialScope): access normally when shape is updated. + credentialScope: (Credentials as any).CredentialScope, + }; + }; +}; diff --git a/packages/credential-providers/src/fromTemporaryCredentials.browser.ts b/packages/credential-providers/src/fromTemporaryCredentials.browser.ts index 28c92364070d..9bcd22de9426 100644 --- a/packages/credential-providers/src/fromTemporaryCredentials.browser.ts +++ b/packages/credential-providers/src/fromTemporaryCredentials.browser.ts @@ -1,75 +1 @@ -import type { AssumeRoleCommandInput, STSClient, STSClientConfig } from "@aws-sdk/nested-clients/sts"; -import type { - AwsIdentityProperties, - CredentialProviderOptions, - RuntimeConfigAwsCredentialIdentityProvider, -} from "@aws-sdk/types"; -import { CredentialsProviderError } from "@smithy/property-provider"; -import { AwsCredentialIdentity, AwsCredentialIdentityProvider, Pluggable } from "@smithy/types"; - -export interface FromTemporaryCredentialsOptions extends CredentialProviderOptions { - params: Omit & { RoleSessionName?: string }; - masterCredentials?: AwsCredentialIdentity | AwsCredentialIdentityProvider; - clientConfig?: STSClientConfig; - clientPlugins?: Pluggable[]; - mfaCodeProvider?: (mfaSerial: string) => Promise; -} - -export const fromTemporaryCredentials = ( - options: FromTemporaryCredentialsOptions, - credentialDefaultProvider?: () => AwsCredentialIdentityProvider -): RuntimeConfigAwsCredentialIdentityProvider => { - let stsClient: STSClient; - return async (awsIdentityProperties: AwsIdentityProperties = {}): Promise => { - options.logger?.debug("@aws-sdk/credential-providers - fromTemporaryCredentials (STS)"); - const params = { ...options.params, RoleSessionName: options.params.RoleSessionName ?? "aws-sdk-js-" + Date.now() }; - if (params?.SerialNumber) { - if (!options.mfaCodeProvider) { - throw new CredentialsProviderError( - `Temporary credential requires multi-factor authentication, but no MFA code callback was provided.`, - { - tryNextLink: false, - logger: options.logger, - } - ); - } - params.TokenCode = await options.mfaCodeProvider(params?.SerialNumber); - } - - const { AssumeRoleCommand, STSClient } = await import("./loadSts"); - - if (!stsClient) { - const defaultCredentialsOrError = - typeof credentialDefaultProvider === "function" ? credentialDefaultProvider() : undefined; - - const { callerClientConfig } = awsIdentityProperties; - stsClient = new STSClient({ - ...options.clientConfig, - credentials: - options.masterCredentials ?? - options.clientConfig?.credentials ?? - callerClientConfig?.credentialDefaultProvider?.() ?? - defaultCredentialsOrError, - }); - } - if (options.clientPlugins) { - for (const plugin of options.clientPlugins) { - stsClient.middlewareStack.use(plugin); - } - } - const { Credentials } = await stsClient.send(new AssumeRoleCommand(params)); - if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) { - throw new CredentialsProviderError(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`, { - logger: options.logger, - }); - } - return { - accessKeyId: Credentials.AccessKeyId, - secretAccessKey: Credentials.SecretAccessKey, - sessionToken: Credentials.SessionToken, - expiration: Credentials.Expiration, - // TODO(credentialScope): access normally when shape is updated. - credentialScope: (Credentials as any).CredentialScope, - }; - }; -}; +export { FromTemporaryCredentialsOptions, fromTemporaryCredentials } from "./fromTemporaryCredentials.base"; diff --git a/packages/credential-providers/src/fromTemporaryCredentials.spec.ts b/packages/credential-providers/src/fromTemporaryCredentials.spec.ts index ea0f512e63a8..f9bc202a2791 100644 --- a/packages/credential-providers/src/fromTemporaryCredentials.spec.ts +++ b/packages/credential-providers/src/fromTemporaryCredentials.spec.ts @@ -1,8 +1,8 @@ import { AssumeRoleCommand, STSClient } from "@aws-sdk/nested-clients/sts"; -import { afterEach, beforeEach, describe, expect, test as it, vi } from "vitest"; +import { beforeEach, describe, expect, test as it, vi } from "vitest"; import { fromTemporaryCredentials as fromTemporaryCredentialsNode } from "./fromTemporaryCredentials"; -import { fromTemporaryCredentials } from "./fromTemporaryCredentials.browser"; +import { fromTemporaryCredentials } from "./fromTemporaryCredentials.base"; const mockSend = vi.fn(); const mockUsePlugin = vi.fn(); diff --git a/packages/credential-providers/src/fromTemporaryCredentials.ts b/packages/credential-providers/src/fromTemporaryCredentials.ts index 679e0c66b8e4..5ccbeddd038e 100644 --- a/packages/credential-providers/src/fromTemporaryCredentials.ts +++ b/packages/credential-providers/src/fromTemporaryCredentials.ts @@ -1,8 +1,8 @@ import type { RuntimeConfigAwsCredentialIdentityProvider } from "@aws-sdk/types"; import { fromNodeProviderChain } from "./fromNodeProviderChain"; -import type { FromTemporaryCredentialsOptions } from "./fromTemporaryCredentials.browser"; -import { fromTemporaryCredentials as fromTemporaryCredentialsBase } from "./fromTemporaryCredentials.browser"; +import type { FromTemporaryCredentialsOptions } from "./fromTemporaryCredentials.base"; +import { fromTemporaryCredentials as fromTemporaryCredentialsBase } from "./fromTemporaryCredentials.base"; /** * @public