Skip to content

Commit 7226996

Browse files
committed
feat(sts): use constructor if itself for assumerole
1 parent 0745502 commit 7226996

File tree

13 files changed

+467
-5
lines changed

13 files changed

+467
-5
lines changed

clients/client-sts/STSClient.ts

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,8 @@ import {
3030
} from "@aws-sdk/middleware-host-header";
3131
import { getLoggerPlugin } from "@aws-sdk/middleware-logger";
3232
import { RetryInputConfig, RetryResolvedConfig, getRetryPlugin, resolveRetryConfig } from "@aws-sdk/middleware-retry";
33-
import { AwsAuthInputConfig, AwsAuthResolvedConfig, resolveAwsAuthConfig } from "@aws-sdk/middleware-signing";
33+
// import { AwsAuthInputConfig, AwsAuthResolvedConfig, resolveAwsAuthConfig } from "@aws-sdk/middleware-signing";
34+
import { StsAuthInputConfig, StsAuthResolvedConfig, resolveStsAuthConfig } from "@aws-sdk/middleware-sdk-sts";
3435
import {
3536
UserAgentInputConfig,
3637
UserAgentResolvedConfig,
@@ -180,7 +181,8 @@ export type STSClientConfig = Partial<__SmithyConfiguration<__HttpHandlerOptions
180181
EndpointsInputConfig &
181182
RetryInputConfig &
182183
HostHeaderInputConfig &
183-
AwsAuthInputConfig &
184+
// AwsAuthInputConfig &
185+
StsAuthInputConfig &
184186
UserAgentInputConfig;
185187

186188
export type STSClientResolvedConfig = __SmithyResolvedConfiguration<__HttpHandlerOptions> &
@@ -189,7 +191,8 @@ export type STSClientResolvedConfig = __SmithyResolvedConfiguration<__HttpHandle
189191
EndpointsResolvedConfig &
190192
RetryResolvedConfig &
191193
HostHeaderResolvedConfig &
192-
AwsAuthResolvedConfig &
194+
// AwsAuthResolvedConfig &
195+
StsAuthResolvedConfig &
193196
UserAgentResolvedConfig;
194197

195198
/**
@@ -216,7 +219,8 @@ export class STSClient extends __Client<
216219
let _config_2 = resolveEndpointsConfig(_config_1);
217220
let _config_3 = resolveRetryConfig(_config_2);
218221
let _config_4 = resolveHostHeaderConfig(_config_3);
219-
let _config_5 = resolveAwsAuthConfig(_config_4);
222+
// let _config_5 = resolveAwsAuthConfig(_config_4);
223+
let _config_5 = resolveStsAuthConfig(_config_4, STSClient);
220224
let _config_6 = resolveUserAgentConfig(_config_5);
221225
super(_config_6);
222226
this.config = _config_6;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import {
2+
DefaultCredentialProvider,
3+
getDefaultRoleAssumer as StsGetDefaultRoleAssumer,
4+
getDefaultRoleAssumerWithWebIdentity as StsGetDefaultRoleAssumerWithWebIdentity,
5+
RoleAssumer,
6+
RoleAssumerWithWebIdentity,
7+
} from "./defaultStsRoleAssumers";
8+
import { STSClient, STSClientConfig } from "./STSClient";
9+
10+
export const getDefaultRoleAssumer = (stsOptions: Pick<STSClientConfig, "logger" | "region">): RoleAssumer =>
11+
StsGetDefaultRoleAssumer(stsOptions, STSClient);
12+
13+
export const getDefaultRoleAssumerWithWebIdentity = (
14+
stsOptions: Pick<STSClientConfig, "logger" | "region">
15+
): RoleAssumerWithWebIdentity => StsGetDefaultRoleAssumerWithWebIdentity(stsOptions, STSClient);
16+
17+
export const decorateDefaultCredentialProvider = (provider: DefaultCredentialProvider): DefaultCredentialProvider => (
18+
input: any
19+
) =>
20+
provider({
21+
roleAssumer: getDefaultRoleAssumer(input),
22+
roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(input),
23+
...input,
24+
});
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import { Credentials, Provider } from "@aws-sdk/types";
2+
3+
import { AssumeRoleCommand, AssumeRoleCommandInput } from "./commands/AssumeRoleCommand";
4+
import {
5+
AssumeRoleWithWebIdentityCommand,
6+
AssumeRoleWithWebIdentityCommandInput,
7+
} from "./commands/AssumeRoleWithWebIdentityCommand";
8+
import type { STSClient, STSClientConfig, STSClientResolvedConfig } from "./STSClient";
9+
10+
/**
11+
* @internal
12+
*/
13+
export type RoleAssumer = (sourceCreds: Credentials, params: AssumeRoleCommandInput) => Promise<Credentials>;
14+
15+
const ASSUME_ROLE_DEFAULT_REGION = "us-east-1";
16+
17+
/**
18+
* Inject the fallback STS region of us-east-1.
19+
*/
20+
const decorateDefaultRegion = (region: string | Provider<string> | undefined): string | Provider<string> => {
21+
if (typeof region !== "function") {
22+
return region === undefined ? ASSUME_ROLE_DEFAULT_REGION : region;
23+
}
24+
return async () => {
25+
try {
26+
return await region();
27+
} catch (e) {
28+
return ASSUME_ROLE_DEFAULT_REGION;
29+
}
30+
};
31+
};
32+
33+
/**
34+
* The default role assumer that used by credential providers when sts:AssumeRole API is needed.
35+
* @internal
36+
*/
37+
export const getDefaultRoleAssumer = (
38+
stsOptions: Pick<STSClientConfig, "logger" | "region">,
39+
stsClientCtor: new (options: STSClientConfig) => STSClient
40+
): RoleAssumer => {
41+
let stsClient: STSClient;
42+
return async (sourceCreds, params) => {
43+
if (!stsClient) {
44+
const { logger, region } = stsOptions;
45+
stsClient = new stsClientCtor({
46+
logger,
47+
credentials: sourceCreds,
48+
region: decorateDefaultRegion(region),
49+
});
50+
}
51+
const { Credentials } = await stsClient.send(new AssumeRoleCommand(params));
52+
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
53+
throw new Error(`Invalid response from STS.assumeRole call with role ${params.RoleArn}`);
54+
}
55+
return {
56+
accessKeyId: Credentials.AccessKeyId,
57+
secretAccessKey: Credentials.SecretAccessKey,
58+
sessionToken: Credentials.SessionToken,
59+
expiration: Credentials.Expiration,
60+
};
61+
};
62+
};
63+
64+
/**
65+
* @internal
66+
*/
67+
export type RoleAssumerWithWebIdentity = (params: AssumeRoleWithWebIdentityCommandInput) => Promise<Credentials>;
68+
69+
/**
70+
* The default role assumer that used by credential providers when sts:AssumeRoleWithWebIdentity API is needed.
71+
* @internal
72+
*/
73+
export const getDefaultRoleAssumerWithWebIdentity = (
74+
stsOptions: Pick<STSClientConfig, "logger" | "region">,
75+
stsClientCtor: new (options: STSClientConfig) => STSClient
76+
): RoleAssumerWithWebIdentity => {
77+
let stsClient: STSClient;
78+
return async (params) => {
79+
if (!stsClient) {
80+
const { logger, region } = stsOptions;
81+
stsClient = new stsClientCtor({
82+
logger,
83+
region: decorateDefaultRegion(region),
84+
});
85+
}
86+
const { Credentials } = await stsClient.send(new AssumeRoleWithWebIdentityCommand(params));
87+
if (!Credentials || !Credentials.AccessKeyId || !Credentials.SecretAccessKey) {
88+
throw new Error(`Invalid response from STS.assumeRoleWithWebIdentity call with role ${params.RoleArn}`);
89+
}
90+
return {
91+
accessKeyId: Credentials.AccessKeyId,
92+
secretAccessKey: Credentials.SecretAccessKey,
93+
sessionToken: Credentials.SessionToken,
94+
expiration: Credentials.Expiration,
95+
};
96+
};
97+
};
98+
99+
/**
100+
* @internal
101+
*/
102+
export type DefaultCredentialProvider = (input: any) => Provider<Credentials>;
103+
104+
/**
105+
* The default credential providers depend STS client to assume role with desired API: sts:assumeRole,
106+
* sts:assumeRoleWithWebIdentity, etc. This function decorates the default credential provider with role assumers which
107+
* encapsulates the process of calling STS commands. This can only be imported by AWS client packages to avoid circular
108+
* dependencies.
109+
*
110+
* @internal
111+
*/
112+
export const decorateDefaultCredentialProvider = (provider: DefaultCredentialProvider): DefaultCredentialProvider => (
113+
input: STSClientResolvedConfig
114+
) =>
115+
provider({
116+
roleAssumer: getDefaultRoleAssumer(input, input.stsClientCtor),
117+
roleAssumerWithWebIdentity: getDefaultRoleAssumerWithWebIdentity(input, input.stsClientCtor),
118+
...input,
119+
});

clients/client-sts/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,3 +9,4 @@ export * from "./commands/GetCallerIdentityCommand";
99
export * from "./commands/GetFederationTokenCommand";
1010
export * from "./commands/GetSessionTokenCommand";
1111
export * from "./models/index";
12+
export * from "./defaultRoleAssumers";

clients/client-sts/package.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
"@aws-sdk/middleware-host-header": "3.10.0",
3737
"@aws-sdk/middleware-logger": "3.10.0",
3838
"@aws-sdk/middleware-retry": "3.10.0",
39+
"@aws-sdk/middleware-sdk-sts": "3.0.0",
3940
"@aws-sdk/middleware-serde": "3.10.0",
4041
"@aws-sdk/middleware-signing": "3.10.0",
4142
"@aws-sdk/middleware-stack": "3.10.0",
@@ -88,5 +89,11 @@
8889
"type": "git",
8990
"url": "https://github.com/aws/aws-sdk-js-v3.git",
9091
"directory": "clients/client-sts"
92+
},
93+
"exports": {
94+
"./defaultRoleAssumers": {
95+
"import": "./dist/es/defaultRoleAssumers.js",
96+
"require": "./dist/cjs/defaultRoleAssumers.js"
97+
}
9198
}
9299
}

clients/client-sts/runtimeConfig.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import packageInfo from "./package.json";
22

33
import { NODE_REGION_CONFIG_FILE_OPTIONS, NODE_REGION_CONFIG_OPTIONS } from "@aws-sdk/config-resolver";
4+
import { decorateDefaultCredentialProvider } from "./defaultStsRoleAssumers";
45
import { defaultProvider as credentialDefaultProvider } from "@aws-sdk/credential-provider-node";
56
import { Hash } from "@aws-sdk/hash-node";
67
import { NODE_MAX_ATTEMPT_CONFIG_OPTIONS } from "@aws-sdk/middleware-retry";
@@ -22,7 +23,7 @@ export const ClientDefaultValues: Required<ClientDefaults> = {
2223
base64Decoder: fromBase64,
2324
base64Encoder: toBase64,
2425
bodyLengthChecker: calculateBodyLength,
25-
credentialDefaultProvider,
26+
credentialDefaultProvider: decorateDefaultCredentialProvider(credentialDefaultProvider),
2627
defaultUserAgentProvider: defaultUserAgent({
2728
serviceId: ClientSharedValues.serviceId,
2829
clientVersion: packageInfo.version,

0 commit comments

Comments
 (0)